cf8ad44ffe4f931d8f447a32532e9d2df95411ff
[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 (v3.2.0 right now).
96     if ($oldversion < 2016120500) {
97         // Just in case somebody hacks upgrade scripts or env, we really can not continue.
98         echo("You need to upgrade to 3.2.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, 2016120500);
102     }
104     if ($oldversion < 2016122800.00) {
105         // Find all roles with the coursecreator archetype.
106         $coursecreatorroleids = $DB->get_records('role', array('archetype' => 'coursecreator'), '', 'id');
108         $context = context_system::instance();
109         $capability = 'moodle/site:configview';
111         foreach ($coursecreatorroleids as $roleid => $notused) {
113             // Check that the capability has not already been assigned. If it has then it's either already set
114             // to allow or specifically set to prohibit or prevent.
115             if (!$DB->record_exists('role_capabilities', array('roleid' => $roleid, 'capability' => $capability))) {
116                 // Assign the capability.
117                 $cap = new stdClass();
118                 $cap->contextid    = $context->id;
119                 $cap->roleid       = $roleid;
120                 $cap->capability   = $capability;
121                 $cap->permission   = CAP_ALLOW;
122                 $cap->timemodified = time();
123                 $cap->modifierid   = 0;
125                 $DB->insert_record('role_capabilities', $cap);
126             }
127         }
129         // Main savepoint reached.
130         upgrade_main_savepoint(true, 2016122800.00);
131     }
133     if ($oldversion < 2017020200.01) {
135         // Define index useridfrom_timeuserfromdeleted_notification (not unique) to be added to message.
136         $table = new xmldb_table('message');
137         $index = new xmldb_index('useridfrom_timeuserfromdeleted_notification', XMLDB_INDEX_NOTUNIQUE, array('useridfrom', 'timeuserfromdeleted', 'notification'));
139         // Conditionally launch add index useridfrom_timeuserfromdeleted_notification.
140         if (!$dbman->index_exists($table, $index)) {
141             $dbman->add_index($table, $index);
142         }
144         // Define index useridto_timeusertodeleted_notification (not unique) to be added to message.
145         $index = new xmldb_index('useridto_timeusertodeleted_notification', XMLDB_INDEX_NOTUNIQUE, array('useridto', 'timeusertodeleted', 'notification'));
147         // Conditionally launch add index useridto_timeusertodeleted_notification.
148         if (!$dbman->index_exists($table, $index)) {
149             $dbman->add_index($table, $index);
150         }
152         $index = new xmldb_index('useridto', XMLDB_INDEX_NOTUNIQUE, array('useridto'));
154         // Conditionally launch drop index useridto.
155         if ($dbman->index_exists($table, $index)) {
156             $dbman->drop_index($table, $index);
157         }
159         // Main savepoint reached.
160         upgrade_main_savepoint(true, 2017020200.01);
161     }
163     if ($oldversion < 2017020200.02) {
165         // Define index useridfrom_timeuserfromdeleted_notification (not unique) to be added to message_read.
166         $table = new xmldb_table('message_read');
167         $index = new xmldb_index('useridfrom_timeuserfromdeleted_notification', XMLDB_INDEX_NOTUNIQUE, array('useridfrom', 'timeuserfromdeleted', 'notification'));
169         // Conditionally launch add index useridfrom_timeuserfromdeleted_notification.
170         if (!$dbman->index_exists($table, $index)) {
171             $dbman->add_index($table, $index);
172         }
174         // Define index useridto_timeusertodeleted_notification (not unique) to be added to message_read.
175         $index = new xmldb_index('useridto_timeusertodeleted_notification', XMLDB_INDEX_NOTUNIQUE, array('useridto', 'timeusertodeleted', 'notification'));
177         // Conditionally launch add index useridto_timeusertodeleted_notification.
178         if (!$dbman->index_exists($table, $index)) {
179             $dbman->add_index($table, $index);
180         }
182         $index = new xmldb_index('useridto', XMLDB_INDEX_NOTUNIQUE, array('useridto'));
184         // Conditionally launch drop index useridto.
185         if ($dbman->index_exists($table, $index)) {
186             $dbman->drop_index($table, $index);
187         }
189         // Main savepoint reached.
190         upgrade_main_savepoint(true, 2017020200.02);
191     }
193     if ($oldversion < 2017020901.00) {
195         // Delete "orphaned" block positions. Note, the query does not use indexes (because there are none),
196         // if it runs too long during upgrade you can comment this line - it will leave orphaned records
197         // in the database but they won't bother you.
198         upgrade_block_positions();
200         // Main savepoint reached.
201         upgrade_main_savepoint(true, 2017020901.00);
202     }
204     if ($oldversion < 2017021300.00) {
205         unset_config('loginpasswordautocomplete');
206         upgrade_main_savepoint(true, 2017021300.00);
207     }
209     if ($oldversion < 2017021400.00) {
210         // Define field visibleoncoursepage to be added to course_modules.
211         $table = new xmldb_table('course_modules');
212         $field = new xmldb_field('visibleoncoursepage', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'visible');
214         // Conditionally launch add field visibleoncoursepage.
215         if (!$dbman->field_exists($table, $field)) {
216             $dbman->add_field($table, $field);
217         }
219         // Main savepoint reached.
220         upgrade_main_savepoint(true, 2017021400.00);
221     }
223     if ($oldversion < 2017030700.00) {
225         // Define field priority to be added to event.
226         $table = new xmldb_table('event');
227         $field = new xmldb_field('priority', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'subscriptionid');
229         // Conditionally launch add field priority.
230         if (!$dbman->field_exists($table, $field)) {
231             $dbman->add_field($table, $field);
232         }
234         // Main savepoint reached.
235         upgrade_main_savepoint(true, 2017030700.00);
236     }
238     if ($oldversion < 2017031400.00) {
240         // Define table file_conversion to be created.
241         $table = new xmldb_table('file_conversion');
243         // Adding fields to table file_conversion.
244         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
245         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
246         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
247         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
248         $table->add_field('sourcefileid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
249         $table->add_field('targetformat', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
250         $table->add_field('status', XMLDB_TYPE_INTEGER, '10', null, null, null, '0');
251         $table->add_field('statusmessage', XMLDB_TYPE_TEXT, null, null, null, null, null);
252         $table->add_field('converter', XMLDB_TYPE_CHAR, '255', null, null, null, null);
253         $table->add_field('destfileid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
254         $table->add_field('data', XMLDB_TYPE_TEXT, null, null, null, null, null);
256         // Adding keys to table file_conversion.
257         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
258         $table->add_key('sourcefileid', XMLDB_KEY_FOREIGN, array('sourcefileid'), 'files', array('id'));
259         $table->add_key('destfileid', XMLDB_KEY_FOREIGN, array('destfileid'), 'files', array('id'));
261         // Conditionally launch create table for file_conversion.
262         if (!$dbman->table_exists($table)) {
263             $dbman->create_table($table);
264         }
266         // Main savepoint reached.
267         upgrade_main_savepoint(true, 2017031400.00);
268     }
270     if ($oldversion < 2017040400.00) {
272         // If block_course_overview is no longer present, replace with block_myoverview.
273         if (!file_exists($CFG->dirroot . '/blocks/course_overview/block_course_overview.php')) {
274             $DB->set_field('block_instances', 'blockname', 'myoverview', array('blockname' => 'course_overview'));
275         }
277         upgrade_main_savepoint(true, 2017040400.00);
278     }
280     if ($oldversion < 2017040401.00) {
282         // If block_course_overview is no longer present, remove it.
283         // Note - we do not need to completely remove the block context etc because we
284         // have replaced all occurrences of block_course_overview with block_myoverview
285         // in the upgrade step above.
286         if (!file_exists($CFG->dirroot . '/blocks/course_overview/block_course_overview.php')) {
287             // Delete the block from the block table.
288             $DB->delete_records('block', array('name' => 'course_overview'));
289             // Remove capabilities.
290             capabilities_cleanup('block_course_overview');
291             // Clean config.
292             unset_all_config_for_plugin('block_course_overview');
293         }
295         upgrade_main_savepoint(true, 2017040401.00);
296     }
298     if ($oldversion < 2017040402.00) {
300         // Define fields to be added to the 'event' table.
301         $table = new xmldb_table('event');
302         $fieldtype = new xmldb_field('type', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, 0, 'instance');
303         $fieldtimesort = new xmldb_field('timesort', XMLDB_TYPE_INTEGER, '10', null, false, null, null, 'timeduration');
305         // Conditionally launch add field.
306         if (!$dbman->field_exists($table, $fieldtype)) {
307             $dbman->add_field($table, $fieldtype);
308         }
310         // Conditionally launch add field.
311         if (!$dbman->field_exists($table, $fieldtimesort)) {
312             $dbman->add_field($table, $fieldtimesort);
313         }
315         // Now, define the index we will be adding.
316         $index = new xmldb_index('type-timesort', XMLDB_INDEX_NOTUNIQUE, array('type', 'timesort'));
318         // Conditionally launch add index.
319         if (!$dbman->index_exists($table, $index)) {
320             $dbman->add_index($table, $index);
321         }
323         upgrade_main_savepoint(true, 2017040402.00);
324     }
326     if ($oldversion < 2017040700.01) {
328         // Define table oauth2_issuer to be created.
329         $table = new xmldb_table('oauth2_issuer');
331         // Adding fields to table oauth2_issuer.
332         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
333         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
334         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
335         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
336         $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
337         $table->add_field('image', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
338         $table->add_field('baseurl', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
339         $table->add_field('clientid', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
340         $table->add_field('clientsecret', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
341         $table->add_field('loginscopes', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
342         $table->add_field('loginscopesoffline', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
343         $table->add_field('loginparams', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
344         $table->add_field('loginparamsoffline', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
345         $table->add_field('alloweddomains', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
346         $table->add_field('scopessupported', XMLDB_TYPE_TEXT, null, null, null, null, null);
347         $table->add_field('showonloginpage', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1');
348         $table->add_field('enabled', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1');
349         $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
351         // Adding keys to table oauth2_issuer.
352         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
354         // Conditionally launch create table for oauth2_issuer.
355         if (!$dbman->table_exists($table)) {
356             $dbman->create_table($table);
357         }
359         // Main savepoint reached.
360         upgrade_main_savepoint(true, 2017040700.01);
361     }
363     if ($oldversion < 2017040700.02) {
365         // Define table oauth2_endpoint to be created.
366         $table = new xmldb_table('oauth2_endpoint');
368         // Adding fields to table oauth2_endpoint.
369         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
370         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
371         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
372         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
373         $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
374         $table->add_field('url', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
375         $table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
377         // Adding keys to table oauth2_endpoint.
378         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
379         $table->add_key('issuer_id_key', XMLDB_KEY_FOREIGN, array('issuerid'), 'oauth2_issuer', array('id'));
381         // Conditionally launch create table for oauth2_endpoint.
382         if (!$dbman->table_exists($table)) {
383             $dbman->create_table($table);
384         }
386         // Main savepoint reached.
387         upgrade_main_savepoint(true, 2017040700.02);
388     }
390     if ($oldversion < 2017040700.03) {
392         // Define table oauth2_system_account to be created.
393         $table = new xmldb_table('oauth2_system_account');
395         // Adding fields to table oauth2_system_account.
396         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
397         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
398         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
399         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
400         $table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
401         $table->add_field('refreshtoken', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
402         $table->add_field('grantedscopes', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
403         $table->add_field('username', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
404         $table->add_field('email', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
406         // Adding keys to table oauth2_system_account.
407         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
408         $table->add_key('issueridkey', XMLDB_KEY_FOREIGN_UNIQUE, array('issuerid'), 'oauth2_issuer', array('id'));
410         // Conditionally launch create table for oauth2_system_account.
411         if (!$dbman->table_exists($table)) {
412             $dbman->create_table($table);
413         }
415         // Main savepoint reached.
416         upgrade_main_savepoint(true, 2017040700.03);
417     }
419     if ($oldversion < 2017040700.04) {
421         // Define table oauth2_user_field_mapping to be created.
422         $table = new xmldb_table('oauth2_user_field_mapping');
424         // Adding fields to table oauth2_user_field_mapping.
425         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
426         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
427         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
428         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
429         $table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
430         $table->add_field('externalfield', XMLDB_TYPE_CHAR, '64', null, XMLDB_NOTNULL, null, null);
431         $table->add_field('internalfield', XMLDB_TYPE_CHAR, '64', null, XMLDB_NOTNULL, null, null);
433         // Adding keys to table oauth2_user_field_mapping.
434         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
435         $table->add_key('issuerkey', XMLDB_KEY_FOREIGN, array('issuerid'), 'oauth2_issuer', array('id'));
436         $table->add_key('uniqinternal', XMLDB_KEY_UNIQUE, array('issuerid', 'internalfield'));
438         // Conditionally launch create table for oauth2_user_field_mapping.
439         if (!$dbman->table_exists($table)) {
440             $dbman->create_table($table);
441         }
443         // Main savepoint reached.
444         upgrade_main_savepoint(true, 2017040700.04);
445     }
447     if ($oldversion < 2017041801.00) {
449         // Define table course_completion_defaults to be created.
450         $table = new xmldb_table('course_completion_defaults');
452         // Adding fields to table course_completion_defaults.
453         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
454         $table->add_field('course', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
455         $table->add_field('module', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
456         $table->add_field('completion', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
457         $table->add_field('completionview', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
458         $table->add_field('completionusegrade', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
459         $table->add_field('completionexpected', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
460         $table->add_field('customrules', XMLDB_TYPE_TEXT, null, null, null, null, null);
462         // Adding keys to table course_completion_defaults.
463         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
464         $table->add_key('module', XMLDB_KEY_FOREIGN, array('module'), 'modules', array('id'));
465         $table->add_key('course', XMLDB_KEY_FOREIGN, array('course'), 'course', array('id'));
467         // Adding indexes to table course_completion_defaults.
468         $table->add_index('coursemodule', XMLDB_INDEX_UNIQUE, array('course', 'module'));
470         // Conditionally launch create table for course_completion_defaults.
471         if (!$dbman->table_exists($table)) {
472             $dbman->create_table($table);
473         }
475         upgrade_main_savepoint(true, 2017041801.00);
476     }
478     if ($oldversion < 2017050500.01) {
479         // Get the list of parent event IDs.
480         $sql = "SELECT DISTINCT repeatid
481                            FROM {event}
482                           WHERE repeatid <> 0";
483         $parentids = array_keys($DB->get_records_sql($sql));
484         // Check if there are repeating events we need to process.
485         if (!empty($parentids)) {
486             // The repeat IDs of parent events should match their own ID.
487             // So we need to update parent events that have non-matching IDs and repeat IDs.
488             list($insql, $params) = $DB->get_in_or_equal($parentids);
489             $updatesql = "UPDATE {event}
490                              SET repeatid = id
491                            WHERE id <> repeatid
492                                  AND id $insql";
493             $DB->execute($updatesql, $params);
494         }
496         // Main savepoint reached.
497         upgrade_main_savepoint(true, 2017050500.01);
498     }
500     if ($oldversion < 2017050500.02) {
501         // MDL-58684:
502         // Remove all portfolio_tempdata records as these may contain serialized \file_system type objects, which are now unable to
503         // be unserialized because of changes to the file storage API made in MDL-46375. Portfolio now stores an id reference to
504         // files instead of the object.
505         // These records are normally removed after a successful export, however, can be left behind if the user abandons the
506         // export attempt (a stale record). Additionally, each stale record cannot be reused and is normally cleaned up by the cron
507         // task core\task\portfolio_cron_task. Since the cron task tries to unserialize them, and generates a warning, we'll remove
508         // all records here.
509         $DB->delete_records_select('portfolio_tempdata', 'id > ?', [0]);
511         // Main savepoint reached.
512         upgrade_main_savepoint(true, 2017050500.02);
513     }
515     if ($oldversion < 2017050900.01) {
516         // Create adhoc task for upgrading of existing calendar events.
517         $record = new \stdClass();
518         $record->classname = '\core\task\refresh_mod_calendar_events_task';
519         $record->component = 'core';
521         // Next run time based from nextruntime computation in \core\task\manager::queue_adhoc_task().
522         $nextruntime = time() - 1;
523         $record->nextruntime = $nextruntime;
524         $DB->insert_record('task_adhoc', $record);
526         // Main savepoint reached.
527         upgrade_main_savepoint(true, 2017050900.01);
528     }
530     // Automatically generated Moodle v3.3.0 release upgrade line.
531     // Put any upgrade step following this.
533     if ($oldversion < 2017061201.00) {
534         $table = new xmldb_table('course_sections');
535         $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'availability');
537         // Define a field 'timemodified' in the 'course_sections' table.
538         if (!$dbman->field_exists($table, $field)) {
539             $dbman->add_field($table, $field);
540         }
542         upgrade_main_savepoint(true, 2017061201.00);
543     }
545     if ($oldversion < 2017061301.00) {
546         // Check if the value of 'navcourselimit' is set to the old default value, if so, change it to the new default.
547         if ($CFG->navcourselimit == 20) {
548             set_config('navcourselimit', 10);
549         }
551         // Main savepoint reached.
552         upgrade_main_savepoint(true, 2017061301.00);
553     }
555     if ($oldversion < 2017071000.00) {
557         // Define field requireconfirmation to be added to oauth2_issuer.
558         $table = new xmldb_table('oauth2_issuer');
559         $field = new xmldb_field('requireconfirmation', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '1', 'sortorder');
561         // Conditionally launch add field requireconfirmation.
562         if (!$dbman->field_exists($table, $field)) {
563             $dbman->add_field($table, $field);
564         }
566         // Main savepoint reached.
567         upgrade_main_savepoint(true, 2017071000.00);
568     }
570     if ($oldversion < 2017071001.00) {
572         // Define field timemodified to be added to block_instances.
573         $table = new xmldb_table('block_instances');
574         $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null,
575                 null, null, 'configdata');
577         // Conditionally launch add field timemodified.
578         if (!$dbman->field_exists($table, $field)) {
579             $dbman->add_field($table, $field);
581             // Set field to current time.
582             $DB->set_field('block_instances', 'timemodified', time());
584             // Changing nullability of field timemodified on table block_instances to not null.
585             $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL,
586                     null, null, 'configdata');
588             // Launch change of nullability for field timemodified.
589             $dbman->change_field_notnull($table, $field);
591             // Define index timemodified (not unique) to be added to block_instances.
592             $index = new xmldb_index('timemodified', XMLDB_INDEX_NOTUNIQUE, array('timemodified'));
594             // Conditionally launch add index timemodified.
595             if (!$dbman->index_exists($table, $index)) {
596                 $dbman->add_index($table, $index);
597             }
598         }
600         // Define field timecreated to be added to block_instances.
601         $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, null,
602                 null, null, 'configdata');
604         // Conditionally launch add field timecreated.
605         if (!$dbman->field_exists($table, $field)) {
606             $dbman->add_field($table, $field);
608             // Set field to current time.
609             $DB->set_field('block_instances', 'timecreated', time());
611             // Changing nullability of field timecreated on table block_instances to not null.
612             $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL,
613                     null, null, 'configdata');
615             // Launch change of nullability for field timecreated.
616             $dbman->change_field_notnull($table, $field);
617         }
619         // Main savepoint reached.
620         upgrade_main_savepoint(true, 2017071001.00);
621     }
623     if ($oldversion < 2017071100.00 ) {
624         // Clean old upgrade setting not used anymore.
625         unset_config('upgrade_minmaxgradestepignored');
626         upgrade_main_savepoint(true, 2017071100.00);
627     }
629     if ($oldversion < 2017072000.02) {
631         // Define table analytics_models to be created.
632         $table = new xmldb_table('analytics_models');
634         // Adding fields to table analytics_models.
635         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
636         $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
637         $table->add_field('trained', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
638         $table->add_field('target', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
639         $table->add_field('indicators', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
640         $table->add_field('timesplitting', XMLDB_TYPE_CHAR, '255', null, null, null, null);
641         $table->add_field('version', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
642         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
643         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
644         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
646         // Adding keys to table analytics_models.
647         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
649         // Adding indexes to table analytics_models.
650         $table->add_index('enabledandtrained', XMLDB_INDEX_NOTUNIQUE, array('enabled', 'trained'));
652         // Conditionally launch create table for analytics_models.
653         if (!$dbman->table_exists($table)) {
654             $dbman->create_table($table);
655         }
657         // Define table analytics_models_log to be created.
658         $table = new xmldb_table('analytics_models_log');
660         // Adding fields to table analytics_models_log.
661         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
662         $table->add_field('modelid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
663         $table->add_field('version', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
664         $table->add_field('target', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
665         $table->add_field('indicators', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
666         $table->add_field('timesplitting', XMLDB_TYPE_CHAR, '255', null, null, null, null);
667         $table->add_field('score', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, '0');
668         $table->add_field('info', XMLDB_TYPE_TEXT, null, null, null, null, null);
669         $table->add_field('dir', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
670         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
671         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
673         // Adding keys to table analytics_models_log.
674         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
676         // Adding indexes to table analytics_models_log.
677         $table->add_index('modelid', XMLDB_INDEX_NOTUNIQUE, array('modelid'));
679         // Conditionally launch create table for analytics_models_log.
680         if (!$dbman->table_exists($table)) {
681             $dbman->create_table($table);
682         }
684         // Define table analytics_predictions to be created.
685         $table = new xmldb_table('analytics_predictions');
687         // Adding fields to table analytics_predictions.
688         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
689         $table->add_field('modelid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
690         $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
691         $table->add_field('sampleid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
692         $table->add_field('rangeindex', XMLDB_TYPE_INTEGER, '5', null, XMLDB_NOTNULL, null, null);
693         $table->add_field('prediction', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, null);
694         $table->add_field('predictionscore', XMLDB_TYPE_NUMBER, '10, 5', null, XMLDB_NOTNULL, null, null);
695         $table->add_field('calculations', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
696         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
698         // Adding keys to table analytics_predictions.
699         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
701         // Adding indexes to table analytics_predictions.
702         $table->add_index('modelidandcontextid', XMLDB_INDEX_NOTUNIQUE, array('modelid', 'contextid'));
704         // Conditionally launch create table for analytics_predictions.
705         if (!$dbman->table_exists($table)) {
706             $dbman->create_table($table);
707         }
709         // Define table analytics_train_samples to be created.
710         $table = new xmldb_table('analytics_train_samples');
712         // Adding fields to table analytics_train_samples.
713         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
714         $table->add_field('modelid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
715         $table->add_field('analysableid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
716         $table->add_field('timesplitting', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
717         $table->add_field('fileid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
718         $table->add_field('sampleids', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
719         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
721         // Adding keys to table analytics_train_samples.
722         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
724         // Adding indexes to table analytics_train_samples.
725         $table->add_index('modelidandanalysableidandtimesplitting', XMLDB_INDEX_NOTUNIQUE,
726             array('modelid', 'analysableid', 'timesplitting'));
728         // Conditionally launch create table for analytics_train_samples.
729         if (!$dbman->table_exists($table)) {
730             $dbman->create_table($table);
731         }
733         // Define table analytics_predict_ranges to be created.
734         $table = new xmldb_table('analytics_predict_ranges');
736         // Adding fields to table analytics_predict_ranges.
737         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
738         $table->add_field('modelid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
739         $table->add_field('analysableid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
740         $table->add_field('timesplitting', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
741         $table->add_field('rangeindex', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
742         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
744         // Adding keys to table analytics_predict_ranges.
745         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
747         // Adding indexes to table analytics_predict_ranges.
748         $table->add_index('modelidandanalysableidandtimesplitting', XMLDB_INDEX_NOTUNIQUE,
749             array('modelid', 'analysableid', 'timesplitting'));
751         // Conditionally launch create table for analytics_predict_ranges.
752         if (!$dbman->table_exists($table)) {
753             $dbman->create_table($table);
754         }
756         // Define table analytics_used_files to be created.
757         $table = new xmldb_table('analytics_used_files');
759         // Adding fields to table analytics_used_files.
760         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
761         $table->add_field('modelid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
762         $table->add_field('fileid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
763         $table->add_field('action', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL, null, null);
764         $table->add_field('time', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
766         // Adding keys to table analytics_used_files.
767         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
769         // Adding indexes to table analytics_used_files.
770         $table->add_index('modelidandfileidandaction', XMLDB_INDEX_NOTUNIQUE, array('modelid', 'fileid', 'action'));
772         // Conditionally launch create table for analytics_used_files.
773         if (!$dbman->table_exists($table)) {
774             $dbman->create_table($table);
775         }
777         $now = time();
778         $admin = get_admin();
780         $targetname = '\core\analytics\target\course_dropout';
781         if (!$DB->record_exists('analytics_models', array('target' => $targetname))) {
782             // We can not use API calls to create the built-in models.
783             $modelobj = new stdClass();
784             $modelobj->target = $targetname;
785             $modelobj->indicators = json_encode(array(
786                 '\mod_assign\analytics\indicator\cognitive_depth',
787                 '\mod_assign\analytics\indicator\social_breadth',
788                 '\mod_book\analytics\indicator\cognitive_depth',
789                 '\mod_book\analytics\indicator\social_breadth',
790                 '\mod_chat\analytics\indicator\cognitive_depth',
791                 '\mod_chat\analytics\indicator\social_breadth',
792                 '\mod_choice\analytics\indicator\cognitive_depth',
793                 '\mod_choice\analytics\indicator\social_breadth',
794                 '\mod_data\analytics\indicator\cognitive_depth',
795                 '\mod_data\analytics\indicator\social_breadth',
796                 '\mod_feedback\analytics\indicator\cognitive_depth',
797                 '\mod_feedback\analytics\indicator\social_breadth',
798                 '\mod_folder\analytics\indicator\cognitive_depth',
799                 '\mod_folder\analytics\indicator\social_breadth',
800                 '\mod_forum\analytics\indicator\cognitive_depth',
801                 '\mod_forum\analytics\indicator\social_breadth',
802                 '\mod_glossary\analytics\indicator\cognitive_depth',
803                 '\mod_glossary\analytics\indicator\social_breadth',
804                 '\mod_imscp\analytics\indicator\cognitive_depth',
805                 '\mod_imscp\analytics\indicator\social_breadth',
806                 '\mod_label\analytics\indicator\cognitive_depth',
807                 '\mod_label\analytics\indicator\social_breadth',
808                 '\mod_lesson\analytics\indicator\cognitive_depth',
809                 '\mod_lesson\analytics\indicator\social_breadth',
810                 '\mod_lti\analytics\indicator\cognitive_depth',
811                 '\mod_lti\analytics\indicator\social_breadth',
812                 '\mod_page\analytics\indicator\cognitive_depth',
813                 '\mod_page\analytics\indicator\social_breadth',
814                 '\mod_quiz\analytics\indicator\cognitive_depth',
815                 '\mod_quiz\analytics\indicator\social_breadth',
816                 '\mod_resource\analytics\indicator\cognitive_depth',
817                 '\mod_resource\analytics\indicator\social_breadth',
818                 '\mod_scorm\analytics\indicator\cognitive_depth',
819                 '\mod_scorm\analytics\indicator\social_breadth',
820                 '\mod_survey\analytics\indicator\cognitive_depth',
821                 '\mod_survey\analytics\indicator\social_breadth',
822                 '\mod_url\analytics\indicator\cognitive_depth',
823                 '\mod_url\analytics\indicator\social_breadth',
824                 '\mod_wiki\analytics\indicator\cognitive_depth',
825                 '\mod_wiki\analytics\indicator\social_breadth',
826                 '\mod_workshop\analytics\indicator\cognitive_depth',
827                 '\mod_workshop\analytics\indicator\social_breadth',
828             ));
829             $modelobj->version = $now;
830             $modelobj->timecreated = $now;
831             $modelobj->timemodified = $now;
832             $modelobj->usermodified = $admin->id;
833             $DB->insert_record('analytics_models', $modelobj);
834         }
836         $targetname = '\core\analytics\target\no_teaching';
837         if (!$DB->record_exists('analytics_models', array('target' => $targetname))) {
838             $modelobj = new stdClass();
839             $modelobj->enabled = 1;
840             $modelobj->trained = 1;
841             $modelobj->target = $targetname;
842             $modelobj->indicators = json_encode(array('\core_course\analytics\indicator\no_teacher'));
843             $modelobj->timesplitting = '\core\analytics\time_splitting\single_range';
844             $modelobj->version = $now;
845             $modelobj->timecreated = $now;
846             $modelobj->timemodified = $now;
847             $modelobj->usermodified = $admin->id;
848             $DB->insert_record('analytics_models', $modelobj);
849         }
851         // Main savepoint reached.
852         upgrade_main_savepoint(true, 2017072000.02);
853     }
855     if ($oldversion < 2017072700.01) {
856         // Changing nullability of field email on table oauth2_system_account to null.
857         $table = new xmldb_table('oauth2_system_account');
858         $field = new xmldb_field('email', XMLDB_TYPE_TEXT, null, null, null, null, null, 'grantedscopes');
860         // Launch change of nullability for field email.
861         $dbman->change_field_notnull($table, $field);
863         // Main savepoint reached.
864         upgrade_main_savepoint(true, 2017072700.01);
865     }
867     if ($oldversion < 2017072700.02) {
869         // If the site was previously registered with http://hub.moodle.org change the registration to
870         // point to https://moodle.net - this is the correct hub address using https protocol.
871         $oldhuburl = "http://hub.moodle.org";
872         $newhuburl = "https://moodle.net";
873         $cleanoldhuburl = preg_replace('/[^A-Za-z0-9_-]/i', '', $oldhuburl);
874         $cleannewhuburl = preg_replace('/[^A-Za-z0-9_-]/i', '', $newhuburl);
876         // Update existing registration.
877         $DB->execute("UPDATE {registration_hubs} SET hubname = ?, huburl = ? WHERE huburl = ?",
878             ['Moodle.net', $newhuburl, $oldhuburl]);
880         // Update settings of existing registration.
881         $sqlnamelike = $DB->sql_like('name', '?');
882         $entries = $DB->get_records_sql("SELECT * FROM {config_plugins} where plugin=? and " . $sqlnamelike,
883             ['hub', '%' . $DB->sql_like_escape('_' . $cleanoldhuburl)]);
884         foreach ($entries as $entry) {
885             $newname = substr($entry->name, 0, -strlen($cleanoldhuburl)) . $cleannewhuburl;
886             try {
887                 $DB->update_record('config_plugins', ['id' => $entry->id, 'name' => $newname]);
888             } catch (dml_exception $e) {
889                 // Entry with new name already exists, remove the one with an old name.
890                 $DB->delete_records('config_plugins', ['id' => $entry->id]);
891             }
892         }
894         // Update published courses.
895         $DB->execute('UPDATE {course_published} SET huburl = ? WHERE huburl = ?', [$newhuburl, $oldhuburl]);
897         // Main savepoint reached.
898         upgrade_main_savepoint(true, 2017072700.02);
899     }
901     if ($oldversion < 2017080700.01) {
903         // Get the table by its previous name.
904         $table = new xmldb_table('analytics_predict_ranges');
905         if ($dbman->table_exists($table)) {
907             // We can only accept this because we are in master.
908             $DB->delete_records('analytics_predictions');
909             $DB->delete_records('analytics_used_files', array('action' => 'predicted'));
910             $DB->delete_records('analytics_predict_ranges');
912             // Define field sampleids to be added to analytics_predict_ranges (renamed below to analytics_predict_samples).
913             $field = new xmldb_field('sampleids', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null, 'rangeindex');
915             // Conditionally launch add field sampleids.
916             if (!$dbman->field_exists($table, $field)) {
917                 $dbman->add_field($table, $field);
918             }
920             // Define field timemodified to be added to analytics_predict_ranges (renamed below to analytics_predict_samples).
921             $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'timecreated');
923             // Conditionally launch add field timemodified.
924             if (!$dbman->field_exists($table, $field)) {
925                 $dbman->add_field($table, $field);
926             }
928             // Rename the table to its new name.
929             $dbman->rename_table($table, 'analytics_predict_samples');
930         }
932         $table = new xmldb_table('analytics_predict_samples');
934         $index = new xmldb_index('modelidandanalysableidandtimesplitting', XMLDB_INDEX_NOTUNIQUE,
935             array('modelid', 'analysableid', 'timesplitting'));
937         // Conditionally launch drop index.
938         if ($dbman->index_exists($table, $index)) {
939             $dbman->drop_index($table, $index);
940         }
942         $index = new xmldb_index('modelidandanalysableidandtimesplittingandrangeindex', XMLDB_INDEX_NOTUNIQUE,
943             array('modelid', 'analysableid', 'timesplitting', 'rangeindex'));
945         // Conditionally launch add index.
946         if (!$dbman->index_exists($table, $index)) {
947             $dbman->add_index($table, $index);
948         }
950         // Main savepoint reached.
951         upgrade_main_savepoint(true, 2017080700.01);
952     }
954     if ($oldversion < 2017082200.00) {
955         $plugins = ['radius', 'fc', 'nntp', 'pam', 'pop3', 'imap'];
957         foreach ($plugins as $plugin) {
958             // Check to see if the plugin exists on disk.
959             // If it does not, remove the config for it.
960             if (!file_exists($CFG->dirroot . "/auth/{$plugin}/auth.php")) {
961                 // Clean config.
962                 unset_all_config_for_plugin("auth_{$plugin}");
963             }
964         }
965         upgrade_main_savepoint(true, 2017082200.00);
966     }
968     if ($oldversion < 2017082200.01) {
970         // Define table analytics_indicator_calc to be created.
971         $table = new xmldb_table('analytics_indicator_calc');
973         // Adding fields to table analytics_indicator_calc.
974         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
975         $table->add_field('starttime', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
976         $table->add_field('endtime', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
977         $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
978         $table->add_field('sampleorigin', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
979         $table->add_field('sampleid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
980         $table->add_field('indicator', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
981         $table->add_field('value', XMLDB_TYPE_NUMBER, '10, 2', null, null, null, null);
982         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
984         // Adding keys to table analytics_indicator_calc.
985         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
987         // Adding indexes to table analytics_indicator_calc.
988         $table->add_index('starttime-endtime-contextid', XMLDB_INDEX_NOTUNIQUE, array('starttime', 'endtime', 'contextid'));
990         // Conditionally launch create table for analytics_indicator_calc.
991         if (!$dbman->table_exists($table)) {
992             $dbman->create_table($table);
993         }
995         // Main savepoint reached.
996         upgrade_main_savepoint(true, 2017082200.01);
997     }
999     if ($oldversion < 2017082300.01) {
1001         // This script in included in each major version upgrade process so make sure we don't run it twice.
1002         if (empty($CFG->linkcoursesectionsupgradescriptwasrun)) {
1003             // Check if the site is using a boost-based theme.
1004             // If value of 'linkcoursesections' is set to the old default value, change it to the new default.
1005             if (upgrade_theme_is_from_family('boost', $CFG->theme)) {
1006                 set_config('linkcoursesections', 1);
1007             }
1008             set_config('linkcoursesectionsupgradescriptwasrun', 1);
1009         }
1011         // Main savepoint reached.
1012         upgrade_main_savepoint(true, 2017082300.01);
1013     }
1015     if ($oldversion < 2017082500.00) {
1016         // Handle FKs for the table 'analytics_models_log'.
1017         $table = new xmldb_table('analytics_models_log');
1019         // Remove the existing index before adding FK (which creates an index).
1020         $index = new xmldb_index('modelid', XMLDB_INDEX_NOTUNIQUE, array('modelid'));
1022         // Conditionally launch drop index.
1023         if ($dbman->index_exists($table, $index)) {
1024             $dbman->drop_index($table, $index);
1025         }
1027         // Now, add the FK.
1028         $key = new xmldb_key('modelid', XMLDB_KEY_FOREIGN, array('modelid'), 'analytics_models', array('id'));
1029         $dbman->add_key($table, $key);
1031         // Handle FKs for the table 'analytics_predictions'.
1032         $table = new xmldb_table('analytics_predictions');
1033         $key = new xmldb_key('modelid', XMLDB_KEY_FOREIGN, array('modelid'), 'analytics_models', array('id'));
1034         $dbman->add_key($table, $key);
1036         $key = new xmldb_key('contextid', XMLDB_KEY_FOREIGN, array('contextid'), 'context', array('id'));
1037         $dbman->add_key($table, $key);
1039         // Handle FKs for the table 'analytics_train_samples'.
1040         $table = new xmldb_table('analytics_train_samples');
1041         $key = new xmldb_key('modelid', XMLDB_KEY_FOREIGN, array('modelid'), 'analytics_models', array('id'));
1042         $dbman->add_key($table, $key);
1044         $key = new xmldb_key('fileid', XMLDB_KEY_FOREIGN, array('fileid'), 'files', array('id'));
1045         $dbman->add_key($table, $key);
1047         // Handle FKs for the table 'analytics_predict_samples'.
1048         $table = new xmldb_table('analytics_predict_samples');
1049         $key = new xmldb_key('modelid', XMLDB_KEY_FOREIGN, array('modelid'), 'analytics_models', array('id'));
1050         $dbman->add_key($table, $key);
1052         // Handle FKs for the table 'analytics_used_files'.
1053         $table = new xmldb_table('analytics_used_files');
1054         $key = new xmldb_key('modelid', XMLDB_KEY_FOREIGN, array('modelid'), 'analytics_models', array('id'));
1055         $dbman->add_key($table, $key);
1057         $key = new xmldb_key('fileid', XMLDB_KEY_FOREIGN, array('fileid'), 'files', array('id'));
1058         $dbman->add_key($table, $key);
1060         // Handle FKs for the table 'analytics_indicator_calc'.
1061         $table = new xmldb_table('analytics_indicator_calc');
1062         $key = new xmldb_key('contextid', XMLDB_KEY_FOREIGN, array('contextid'), 'context', array('id'));
1063         $dbman->add_key($table, $key);
1065         // Main savepoint reached.
1066         upgrade_main_savepoint(true, 2017082500.00);
1067     }
1069     if ($oldversion < 2017082800.00) {
1071         // Changing type of field prediction on table analytics_predictions to number.
1072         $table = new xmldb_table('analytics_predictions');
1073         $field = new xmldb_field('prediction', XMLDB_TYPE_NUMBER, '10, 2', null, XMLDB_NOTNULL, null, null, 'rangeindex');
1075         // Launch change of type for field prediction.
1076         $dbman->change_field_type($table, $field);
1078         // Main savepoint reached.
1079         upgrade_main_savepoint(true, 2017082800.00);
1080     }
1082     if ($oldversion < 2017090700.01) {
1084         // Define table analytics_prediction_actions to be created.
1085         $table = new xmldb_table('analytics_prediction_actions');
1087         // Adding fields to table analytics_prediction_actions.
1088         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1089         $table->add_field('predictionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1090         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1091         $table->add_field('actionname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1092         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1094         // Adding keys to table analytics_prediction_actions.
1095         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1096         $table->add_key('predictionid', XMLDB_KEY_FOREIGN, array('predictionid'), 'analytics_predictions', array('id'));
1097         $table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
1099         // Adding indexes to table analytics_prediction_actions.
1100         $table->add_index('predictionidanduseridandactionname', XMLDB_INDEX_NOTUNIQUE,
1101             array('predictionid', 'userid', 'actionname'));
1103         // Conditionally launch create table for analytics_prediction_actions.
1104         if (!$dbman->table_exists($table)) {
1105             $dbman->create_table($table);
1106         }
1108         // Main savepoint reached.
1109         upgrade_main_savepoint(true, 2017090700.01);
1110     }
1112     if ($oldversion < 2017091200.00) {
1113         // Force all messages to be reindexed.
1114         set_config('core_message_message_sent_lastindexrun', '0', 'core_search');
1115         set_config('core_message_message_received_lastindexrun', '0', 'core_search');
1117         // Main savepoint reached.
1118         upgrade_main_savepoint(true, 2017091200.00);
1119     }
1121     if ($oldversion < 2017091201.00) {
1122         // Define field userid to be added to task_adhoc.
1123         $table = new xmldb_table('task_adhoc');
1124         $field = new xmldb_field('userid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'customdata');
1126         // Conditionally launch add field userid.
1127         if (!$dbman->field_exists($table, $field)) {
1128             $dbman->add_field($table, $field);
1129         }
1131         $key = new xmldb_key('useriduser', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
1133         // Launch add key userid_user.
1134         $dbman->add_key($table, $key);
1136         // Main savepoint reached.
1137         upgrade_main_savepoint(true, 2017091201.00);
1138     }
1140     if ($oldversion < 2017092201.00) {
1142         // Remove duplicate registrations.
1143         $newhuburl = "https://moodle.net";
1144         $registrations = $DB->get_records('registration_hubs', ['huburl' => $newhuburl], 'confirmed DESC, id ASC');
1145         if (count($registrations) > 1) {
1146             $reg = array_shift($registrations);
1147             $DB->delete_records_select('registration_hubs', 'huburl = ? AND id <> ?', [$newhuburl, $reg->id]);
1148         }
1150         // Main savepoint reached.
1151         upgrade_main_savepoint(true, 2017092201.00);
1152     }
1154     if ($oldversion < 2017092202.00) {
1156         if (!file_exists($CFG->dirroot . '/blocks/messages/block_messages.php')) {
1158             // Delete instances.
1159             $instances = $DB->get_records_list('block_instances', 'blockname', ['messages']);
1160             $instanceids = array_keys($instances);
1162             if (!empty($instanceids)) {
1163                 $DB->delete_records_list('block_positions', 'blockinstanceid', $instanceids);
1164                 $DB->delete_records_list('block_instances', 'id', $instanceids);
1165                 list($sql, $params) = $DB->get_in_or_equal($instanceids, SQL_PARAMS_NAMED);
1166                 $params['contextlevel'] = CONTEXT_BLOCK;
1167                 $DB->delete_records_select('context', "contextlevel=:contextlevel AND instanceid " . $sql, $params);
1169                 $preferences = array();
1170                 foreach ($instances as $instanceid => $instance) {
1171                     $preferences[] = 'block' . $instanceid . 'hidden';
1172                     $preferences[] = 'docked_block_instance_' . $instanceid;
1173                 }
1174                 $DB->delete_records_list('user_preferences', 'name', $preferences);
1175             }
1177             // Delete the block from the block table.
1178             $DB->delete_records('block', array('name' => 'messages'));
1180             // Remove capabilities.
1181             capabilities_cleanup('block_messages');
1183             // Clean config.
1184             unset_all_config_for_plugin('block_messages');
1185         }
1187         // Main savepoint reached.
1188         upgrade_main_savepoint(true, 2017092202.00);
1189     }
1191     if ($oldversion < 2017092700.00) {
1193         // Rename several fields in registration data to match the names of the properties that are sent to moodle.net.
1194         $renames = [
1195             'site_address_httpsmoodlenet' => 'site_street_httpsmoodlenet',
1196             'site_region_httpsmoodlenet' => 'site_regioncode_httpsmoodlenet',
1197             'site_country_httpsmoodlenet' => 'site_countrycode_httpsmoodlenet'];
1198         foreach ($renames as $oldparamname => $newparamname) {
1199             try {
1200                 $DB->execute("UPDATE {config_plugins} SET name = ? WHERE name = ? AND plugin = ?",
1201                     [$newparamname, $oldparamname, 'hub']);
1202             } catch (dml_exception $e) {
1203                 // Exception can happen if the config value with the new name already exists, ignore it and move on.
1204             }
1205         }
1207         // Main savepoint reached.
1208         upgrade_main_savepoint(true, 2017092700.00);
1209     }
1211     if ($oldversion < 2017092900.00) {
1212         // Define field categoryid to be added to event.
1213         $table = new xmldb_table('event');
1214         $field = new xmldb_field('categoryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'format');
1216         // Conditionally launch add field categoryid.
1217         if (!$dbman->field_exists($table, $field)) {
1218             $dbman->add_field($table, $field);
1219         }
1221         // Add the categoryid key.
1222         $key = new xmldb_key('categoryid', XMLDB_KEY_FOREIGN, array('categoryid'), 'course_categories', array('id'));
1223         $dbman->add_key($table, $key);
1225         // Add a new index for groupid/courseid/categoryid/visible/userid.
1226         // Do this before we remove the old index.
1227         $index = new xmldb_index('groupid-courseid-categoryid-visible-userid', XMLDB_INDEX_NOTUNIQUE, array('groupid', 'courseid', 'categoryid', 'visible', 'userid'));
1228         if (!$dbman->index_exists($table, $index)) {
1229             $dbman->add_index($table, $index);
1230         }
1232         // Drop the old index.
1233         $index = new xmldb_index('groupid-courseid-visible-userid', XMLDB_INDEX_NOTUNIQUE, array('groupid', 'courseid', 'visible', 'userid'));
1234         if ($dbman->index_exists($table, $index)) {
1235             $dbman->drop_index($table, $index);
1236         }
1238         // Main savepoint reached.
1239         upgrade_main_savepoint(true, 2017092900.00);
1240     }
1242     if ($oldversion < 2017100900.00) {
1243         // Add index on time modified to grade_outcomes_history, grade_categories_history,
1244         // grade_items_history, and scale_history.
1245         $table = new xmldb_table('grade_outcomes_history');
1246         $index = new xmldb_index('timemodified', XMLDB_INDEX_NOTUNIQUE, array('timemodified'));
1248         if (!$dbman->index_exists($table, $index)) {
1249             $dbman->add_index($table, $index);
1250         }
1252         $table = new xmldb_table('grade_items_history');
1253         $index = new xmldb_index('timemodified', XMLDB_INDEX_NOTUNIQUE, array('timemodified'));
1255         if (!$dbman->index_exists($table, $index)) {
1256             $dbman->add_index($table, $index);
1257         }
1259         $table = new xmldb_table('grade_categories_history');
1260         $index = new xmldb_index('timemodified', XMLDB_INDEX_NOTUNIQUE, array('timemodified'));
1262         if (!$dbman->index_exists($table, $index)) {
1263             $dbman->add_index($table, $index);
1264         }
1266         $table = new xmldb_table('scale_history');
1267         $index = new xmldb_index('timemodified', XMLDB_INDEX_NOTUNIQUE, array('timemodified'));
1269         if (!$dbman->index_exists($table, $index)) {
1270             $dbman->add_index($table, $index);
1271         }
1273         // Main savepoint reached.
1274         upgrade_main_savepoint(true, 2017100900.00);
1275     }
1277     if ($oldversion < 2017101000.00) {
1279         // Define table analytics_used_analysables to be created.
1280         $table = new xmldb_table('analytics_used_analysables');
1282         // Adding fields to table analytics_used_analysables.
1283         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1284         $table->add_field('modelid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1285         $table->add_field('action', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL, null, null);
1286         $table->add_field('analysableid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1287         $table->add_field('timeanalysed', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1289         // Adding keys to table analytics_used_analysables.
1290         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1291         $table->add_key('modelid', XMLDB_KEY_FOREIGN, array('modelid'), 'analytics_models', array('id'));
1293         // Adding indexes to table analytics_used_analysables.
1294         $table->add_index('modelid-action', XMLDB_INDEX_NOTUNIQUE, array('modelid', 'action'));
1296         // Conditionally launch create table for analytics_used_analysables.
1297         if (!$dbman->table_exists($table)) {
1298             $dbman->create_table($table);
1299         }
1301         // Main savepoint reached.
1302         upgrade_main_savepoint(true, 2017101000.00);
1303     }
1305     if ($oldversion < 2017101000.01) {
1306         // Define field override to be added to course_modules_completion.
1307         $table = new xmldb_table('course_modules_completion');
1308         $field = new xmldb_field('overrideby', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'viewed');
1310         // Conditionally launch add field override.
1311         if (!$dbman->field_exists($table, $field)) {
1312             $dbman->add_field($table, $field);
1313         }
1315         // Main savepoint reached.
1316         upgrade_main_savepoint(true, 2017101000.01);
1317     }
1319     if ($oldversion < 2017101000.02) {
1320         // Define field 'timestart' to be added to 'analytics_predictions'.
1321         $table = new xmldb_table('analytics_predictions');
1322         $field = new xmldb_field('timestart', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'timecreated');
1324         // Conditionally launch add field 'timestart'.
1325         if (!$dbman->field_exists($table, $field)) {
1326             $dbman->add_field($table, $field);
1327         }
1329         // Define field 'timeend' to be added to 'analytics_predictions'.
1330         $field = new xmldb_field('timeend', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'timestart');
1332         // Conditionally launch add field 'timeend'.
1333         if (!$dbman->field_exists($table, $field)) {
1334             $dbman->add_field($table, $field);
1335         }
1337         // Main savepoint reached.
1338         upgrade_main_savepoint(true, 2017101000.02);
1339     }
1341     if ($oldversion < 2017101200.00) {
1342         // Define table search_index_requests to be created.
1343         $table = new xmldb_table('search_index_requests');
1345         // Adding fields to table search_index_requests.
1346         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1347         $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1348         $table->add_field('searcharea', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1349         $table->add_field('timerequested', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1350         $table->add_field('partialarea', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1351         $table->add_field('partialtime', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1353         // Adding keys to table search_index_requests.
1354         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1355         $table->add_key('contextid', XMLDB_KEY_FOREIGN, array('contextid'), 'context', array('id'));
1357         // Conditionally launch create table for search_index_requests.
1358         if (!$dbman->table_exists($table)) {
1359             $dbman->create_table($table);
1360         }
1362         // Main savepoint reached.
1363         upgrade_main_savepoint(true, 2017101200.00);
1364     }
1366     // Index modification upgrade step.
1367     if ($oldversion < 2017101300.01) {
1369         $table = new xmldb_table('analytics_used_files');
1371         // Define index modelidandfileidandaction (not unique) to be dropped form analytics_used_files.
1372         $index = new xmldb_index('modelidandfileidandaction', XMLDB_INDEX_NOTUNIQUE, array('modelid', 'fileid', 'action'));
1374         // Conditionally launch drop index modelidandfileidandaction.
1375         if ($dbman->index_exists($table, $index)) {
1376             $dbman->drop_index($table, $index);
1377         }
1379         // Define index modelidandactionandfileid (not unique) to be dropped form analytics_used_files.
1380         $index = new xmldb_index('modelidandactionandfileid', XMLDB_INDEX_NOTUNIQUE, array('modelid', 'action', 'fileid'));
1382         // Conditionally launch add index modelidandactionandfileid.
1383         if (!$dbman->index_exists($table, $index)) {
1384             $dbman->add_index($table, $index);
1385         }
1387         // Main savepoint reached.
1388         upgrade_main_savepoint(true, 2017101300.01);
1389     }
1391     if ($oldversion < 2017101900.01) {
1393         $fs = get_file_storage();
1394         $models = $DB->get_records('analytics_models');
1395         foreach ($models as $model) {
1396             $files = $fs->get_directory_files(\context_system::instance()->id, 'analytics', 'unlabelled', $model->id,
1397                 '/analysable/', true, true);
1398             foreach ($files as $file) {
1399                 $file->delete();
1400             }
1401         }
1403         // Main savepoint reached.
1404         upgrade_main_savepoint(true, 2017101900.01);
1405     }
1407     if ($oldversion < 2017101900.02) {
1408         // Create adhoc task for upgrading of existing calendar events.
1409         $record = new \stdClass();
1410         $record->classname = '\core\task\refresh_mod_calendar_events_task';
1411         $record->component = 'core';
1413         // Next run time based from nextruntime computation in \core\task\manager::queue_adhoc_task().
1414         $nextruntime = time() - 1;
1415         $record->nextruntime = $nextruntime;
1416         $DB->insert_record('task_adhoc', $record);
1418         // Main savepoint reached.
1419         upgrade_main_savepoint(true, 2017101900.02);
1420     }
1422     if ($oldversion < 2017102100.01) {
1423         // We will need to force them onto ssl if loginhttps is set.
1424         if (!empty($CFG->loginhttps)) {
1425             set_config('overridetossl', 1);
1426         }
1427         // Loginhttps should no longer be set.
1428         unset_config('loginhttps');
1430         // Main savepoint reached.
1431         upgrade_main_savepoint(true, 2017102100.01);
1432     }
1434     if ($oldversion < 2017110300.01) {
1436         // Define field categoryid to be added to event_subscriptions.
1437         $table = new xmldb_table('event_subscriptions');
1438         $field = new xmldb_field('categoryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'url');
1440         // Conditionally launch add field categoryid.
1441         if (!$dbman->field_exists($table, $field)) {
1442             $dbman->add_field($table, $field);
1443         }
1445         // Main savepoint reached.
1446         upgrade_main_savepoint(true, 2017110300.01);
1447     }
1449     // Automatically generated Moodle v3.4.0 release upgrade line.
1450     // Put any upgrade step following this.
1452     if ($oldversion < 2017111300.02) {
1454         // Define field basicauth to be added to oauth2_issuer.
1455         $table = new xmldb_table('oauth2_issuer');
1456         $field = new xmldb_field('basicauth', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'showonloginpage');
1458         // Conditionally launch add field basicauth.
1459         if (!$dbman->field_exists($table, $field)) {
1460             $dbman->add_field($table, $field);
1461         }
1463         // Main savepoint reached.
1464         upgrade_main_savepoint(true, 2017111300.02);
1465     }
1467     if ($oldversion < 2017121200.00) {
1469         // Define key subscriptionid (foreign) to be added to event.
1470         $table = new xmldb_table('event');
1471         $key = new xmldb_key('subscriptionid', XMLDB_KEY_FOREIGN, array('subscriptionid'), 'event_subscriptions', array('id'));
1473         // Launch add key subscriptionid.
1474         $dbman->add_key($table, $key);
1476         // Define index uuid (not unique) to be added to event.
1477         $table = new xmldb_table('event');
1478         $index = new xmldb_index('uuid', XMLDB_INDEX_NOTUNIQUE, array('uuid'));
1480         // Conditionally launch add index uuid.
1481         if (!$dbman->index_exists($table, $index)) {
1482             $dbman->add_index($table, $index);
1483         }
1485         // Main savepoint reached.
1486         upgrade_main_savepoint(true, 2017121200.00);
1487     }
1489     if ($oldversion < 2017121900.00) {
1491         // Define table role_allow_view to be created.
1492         $table = new xmldb_table('role_allow_view');
1494         // Adding fields to table role_allow_view.
1495         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1496         $table->add_field('roleid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1497         $table->add_field('allowview', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1499         // Adding keys to table role_allow_view.
1500         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1501         $table->add_key('roleid', XMLDB_KEY_FOREIGN, array('roleid'), 'role', array('id'));
1502         $table->add_key('allowview', XMLDB_KEY_FOREIGN, array('allowview'), 'role', array('id'));
1504         // Conditionally launch create table for role_allow_view.
1505         if (!$dbman->table_exists($table)) {
1506             $dbman->create_table($table);
1507         }
1509         $index = new xmldb_index('roleid-allowview', XMLDB_INDEX_UNIQUE, array('roleid', 'allowview'));
1511         // Conditionally launch add index roleid.
1512         if (!$dbman->index_exists($table, $index)) {
1513             $dbman->add_index($table, $index);
1514         }
1516         $roles = $DB->get_records('role', array(), 'sortorder ASC');
1518         $DB->delete_records('role_allow_view');
1519         foreach ($roles as $role) {
1520             foreach ($roles as $allowedrole) {
1521                 $record = new stdClass();
1522                 $record->roleid      = $role->id;
1523                 $record->allowview = $allowedrole->id;
1524                 $DB->insert_record('role_allow_view', $record);
1525             }
1526         }
1528         // Main savepoint reached.
1529         upgrade_main_savepoint(true, 2017121900.00);
1530     }
1532     if ($oldversion < 2017122200.01) {
1534         // Define field indexpriority to be added to search_index_requests. Allow null initially.
1535         $table = new xmldb_table('search_index_requests');
1536         $field = new xmldb_field('indexpriority', XMLDB_TYPE_INTEGER, '10',
1537                 null, null, null, null, 'partialtime');
1539         // Conditionally add field.
1540         if (!$dbman->field_exists($table, $field)) {
1541             $dbman->add_field($table, $field);
1543             // Set existing values to 'normal' value (100).
1544             $DB->set_field('search_index_requests', 'indexpriority', 100);
1546             // Now make the field 'NOT NULL'.
1547             $field = new xmldb_field('indexpriority', XMLDB_TYPE_INTEGER, '10',
1548                     null, XMLDB_NOTNULL, null, null, 'partialtime');
1549             $dbman->change_field_notnull($table, $field);
1550         }
1552         // Define index indexprioritytimerequested (not unique) to be added to search_index_requests.
1553         $index = new xmldb_index('indexprioritytimerequested', XMLDB_INDEX_NOTUNIQUE,
1554                 array('indexpriority', 'timerequested'));
1556         // Conditionally launch add index indexprioritytimerequested.
1557         if (!$dbman->index_exists($table, $index)) {
1558             $dbman->add_index($table, $index);
1559         }
1561         // Main savepoint reached.
1562         upgrade_main_savepoint(true, 2017122200.01);
1563     }
1565     if ($oldversion < 2018020500.00) {
1567         $topcategory = new stdClass();
1568         $topcategory->name = 'top'; // A non-real name for the top category. It will be localised at the display time.
1569         $topcategory->info = '';
1570         $topcategory->parent = 0;
1571         $topcategory->sortorder = 0;
1573         // Get the total record count - used for the progress bar.
1574         $total = $DB->count_records_sql("SELECT COUNT(DISTINCT contextid) FROM {question_categories} WHERE parent = 0");
1576         // Get the records themselves - a list of contextids.
1577         $rs = $DB->get_recordset_sql("SELECT DISTINCT contextid FROM {question_categories} WHERE parent = 0");
1579         // For each context, create a single top-level category.
1580         $i = 0;
1581         $pbar = new progress_bar('createtopquestioncategories', 500, true);
1582         foreach ($rs as $contextid => $notused) {
1583             $topcategory->contextid = $contextid;
1584             $topcategory->stamp = make_unique_id_code();
1586             $topcategoryid = $DB->insert_record('question_categories', $topcategory);
1588             $DB->set_field_select('question_categories', 'parent', $topcategoryid,
1589                     'contextid = ? AND id <> ? AND parent = 0',
1590                     array($contextid, $topcategoryid));
1592             // Update progress.
1593             $i++;
1594             $pbar->update($i, $total, "Creating top-level question categories - $i/$total.");
1595         }
1597         $rs->close();
1599         // Main savepoint reached.
1600         upgrade_main_savepoint(true, 2018020500.00);
1601     }
1603     if ($oldversion < 2018022800.01) {
1604         // Fix old block configurations that use the deprecated (and now removed) object class.
1605         upgrade_fix_block_instance_configuration();
1607         // Main savepoint reached.
1608         upgrade_main_savepoint(true, 2018022800.01);
1609     }
1611     if ($oldversion < 2018022800.02) {
1612         // Define index taggeditem (unique) to be dropped form tag_instance.
1613         $table = new xmldb_table('tag_instance');
1614         $index = new xmldb_index('taggeditem', XMLDB_INDEX_UNIQUE, array('component',
1615             'itemtype', 'itemid', 'tiuserid', 'tagid'));
1617         // Conditionally launch drop index taggeditem.
1618         if ($dbman->index_exists($table, $index)) {
1619             $dbman->drop_index($table, $index);
1620         }
1622         $index = new xmldb_index('taggeditem', XMLDB_INDEX_UNIQUE, array('component',
1623             'itemtype', 'itemid', 'contextid', 'tiuserid', 'tagid'));
1625         // Conditionally launch add index taggeditem.
1626         if (!$dbman->index_exists($table, $index)) {
1627             $dbman->add_index($table, $index);
1628         }
1630         // Main savepoint reached.
1631         upgrade_main_savepoint(true, 2018022800.02);
1632     }
1634     if ($oldversion < 2018022800.03) {
1636         // Define field multiplecontexts to be added to tag_area.
1637         $table = new xmldb_table('tag_area');
1638         $field = new xmldb_field('multiplecontexts', XMLDB_TYPE_INTEGER, '1', null,
1639             XMLDB_NOTNULL, null, '0', 'showstandard');
1641         // Conditionally launch add field multiplecontexts.
1642         if (!$dbman->field_exists($table, $field)) {
1643             $dbman->add_field($table, $field);
1644         }
1646         // Main savepoint reached.
1647         upgrade_main_savepoint(true, 2018022800.03);
1648     }
1650     if ($oldversion < 2018032200.01) {
1651         // Define table 'messages' to be created.
1652         $table = new xmldb_table('messages');
1654         // Adding fields to table 'messages'.
1655         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1656         $table->add_field('useridfrom', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1657         $table->add_field('conversationid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1658         $table->add_field('subject', XMLDB_TYPE_TEXT, null, null, null, null, null);
1659         $table->add_field('fullmessage', XMLDB_TYPE_TEXT, null, null, null, null, null);
1660         $table->add_field('fullmessageformat', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0);
1661         $table->add_field('fullmessagehtml', XMLDB_TYPE_TEXT, null, null, null, null, null);
1662         $table->add_field('smallmessage', XMLDB_TYPE_TEXT, null, null, null, null, null);
1663         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1665         // Adding keys to table 'messages'.
1666         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1667         $table->add_key('useridfrom', XMLDB_KEY_FOREIGN, array('useridfrom'), 'user', array('id'));
1668         $table->add_key('conversationid', XMLDB_KEY_FOREIGN, array('conversationid'), 'message_conversations', array('id'));
1670         // Conditionally launch create table for 'messages'.
1671         if (!$dbman->table_exists($table)) {
1672             $dbman->create_table($table);
1673         }
1675         // Define table 'message_conversations' to be created.
1676         $table = new xmldb_table('message_conversations');
1678         // Adding fields to table 'message_conversations'.
1679         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1680         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1682         // Adding keys to table 'message_conversations'.
1683         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1685         // Conditionally launch create table for 'message_conversations'.
1686         if (!$dbman->table_exists($table)) {
1687             $dbman->create_table($table);
1688         }
1690         // Define table 'message_conversation_members' to be created.
1691         $table = new xmldb_table('message_conversation_members');
1693         // Adding fields to table 'message_conversation_members'.
1694         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1695         $table->add_field('conversationid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1696         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1697         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1699         // Adding keys to table 'message_conversation_members'.
1700         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1701         $table->add_key('conversationid', XMLDB_KEY_FOREIGN, array('conversationid'), 'message_conversations', array('id'));
1702         $table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
1704         // Conditionally launch create table for 'message_conversation_members'.
1705         if (!$dbman->table_exists($table)) {
1706             $dbman->create_table($table);
1707         }
1709         // Define table 'message_user_actions' to be created.
1710         $table = new xmldb_table('message_user_actions');
1712         // Adding fields to table 'message_user_actions'.
1713         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1714         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1715         $table->add_field('messageid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1716         $table->add_field('action', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1717         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1719         // Adding keys to table 'message_user_actions'.
1720         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1721         $table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
1722         $table->add_key('messageid', XMLDB_KEY_FOREIGN, array('messageid'), 'messages', array('id'));
1724         // Conditionally launch create table for 'message_user_actions'.
1725         if (!$dbman->table_exists($table)) {
1726             $dbman->create_table($table);
1727         }
1729         // Define table 'notifications' to be created.
1730         $table = new xmldb_table('notifications');
1732         // Adding fields to table 'notifications'.
1733         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1734         $table->add_field('useridfrom', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1735         $table->add_field('useridto', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1736         $table->add_field('subject', XMLDB_TYPE_TEXT, null, null, null, null, null);
1737         $table->add_field('fullmessage', XMLDB_TYPE_TEXT, null, null, null, null, null);
1738         $table->add_field('fullmessageformat', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0);
1739         $table->add_field('fullmessagehtml', XMLDB_TYPE_TEXT, null, null, null, null, null);
1740         $table->add_field('smallmessage', XMLDB_TYPE_TEXT, null, null, null, null, null);
1741         $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1742         $table->add_field('eventtype', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1743         $table->add_field('contexturl', XMLDB_TYPE_TEXT, null, null, null, null, null);
1744         $table->add_field('contexturlname', XMLDB_TYPE_TEXT, null, null, null, null, null);
1745         $table->add_field('timeread', XMLDB_TYPE_INTEGER, '10', null, false, null, null);
1746         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1748         // Adding keys to table 'notifications'.
1749         $table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
1750         $table->add_key('useridto', XMLDB_KEY_FOREIGN, array('useridto'), 'user', array('id'));
1752         // Conditionally launch create table for 'notifications'.
1753         if (!$dbman->table_exists($table)) {
1754             $dbman->create_table($table);
1755         }
1757         // Main savepoint reached.
1758         upgrade_main_savepoint(true, 2018032200.01);
1759     }
1761     if ($oldversion < 2018032200.04) {
1762         // Define table 'message_conversations' to be updated.
1763         $table = new xmldb_table('message_conversations');
1764         $field = new xmldb_field('convhash', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null, 'id');
1766         // Conditionally launch add field 'convhash'.
1767         if (!$dbman->field_exists($table, $field)) {
1768             $dbman->add_field($table, $field);
1769         }
1771         // Conditionally launch add index.
1772         $index = new xmldb_index('convhash', XMLDB_INDEX_UNIQUE, array('convhash'));
1773         if (!$dbman->index_exists($table, $index)) {
1774             $dbman->add_index($table, $index);
1775         }
1777         // Main savepoint reached.
1778         upgrade_main_savepoint(true, 2018032200.04);
1779     }
1781     if ($oldversion < 2018032200.05) {
1782         // Drop table that is no longer needed.
1783         $table = new xmldb_table('message_working');
1784         if ($dbman->table_exists($table)) {
1785             $dbman->drop_table($table);
1786         }
1788         // Main savepoint reached.
1789         upgrade_main_savepoint(true, 2018032200.05);
1790     }
1792     if ($oldversion < 2018032200.06) {
1793         // Define table 'message_user_actions' to add an index to.
1794         $table = new xmldb_table('message_user_actions');
1796         // Conditionally launch add index.
1797         $index = new xmldb_index('userid_messageid_action', XMLDB_INDEX_UNIQUE, array('userid', 'messageid', 'action'));
1798         if (!$dbman->index_exists($table, $index)) {
1799             $dbman->add_index($table, $index);
1800         }
1802         // Main savepoint reached.
1803         upgrade_main_savepoint(true, 2018032200.06);
1804     }
1806     if ($oldversion < 2018032200.07) {
1807         // Define table 'messages' to add an index to.
1808         $table = new xmldb_table('messages');
1810         // Conditionally launch add index.
1811         $index = new xmldb_index('conversationid_timecreated', XMLDB_INDEX_NOTUNIQUE, array('conversationid', 'timecreated'));
1812         if (!$dbman->index_exists($table, $index)) {
1813             $dbman->add_index($table, $index);
1814         }
1816         // Main savepoint reached.
1817         upgrade_main_savepoint(true, 2018032200.07);
1818     }
1820     if ($oldversion < 2018032700.00) {
1821         // Update default search engine to search_simpledb if global search is disabled and there is no solr index defined.
1822         if (empty($CFG->enableglobalsearch) && empty(get_config('search_solr', 'indexname'))) {
1823             set_config('searchengine', 'simpledb');
1824         }
1826         // Main savepoint reached.
1827         upgrade_main_savepoint(true, 2018032700.00);
1828     }
1830     if ($oldversion < 2018040500.01) {
1832         // Define field cohort to be added to theme. Allow null initially.
1833         $table = new xmldb_table('cohort');
1834         $field = new xmldb_field('theme', XMLDB_TYPE_CHAR, '50',
1835                 null, null, null, null, 'timemodified');
1837         // Conditionally add field.
1838         if (!$dbman->field_exists($table, $field)) {
1839             $dbman->add_field($table, $field);
1840         }
1842         // Main savepoint reached.
1843         upgrade_main_savepoint(true, 2018040500.01);
1844     }
1846     if ($oldversion < 2018050900.01) {
1847         // Update default digital age consent map according to the current legislation on each country.
1848         $ageofdigitalconsentmap = implode(PHP_EOL, [
1849             '*, 16',
1850             'AT, 14',
1851             'ES, 14',
1852             'US, 13'
1853         ]);
1854         set_config('agedigitalconsentmap', $ageofdigitalconsentmap);
1856         // Main savepoint reached.
1857         upgrade_main_savepoint(true, 2018050900.01);
1858     }
1860     // Automatically generated Moodle v3.5.0 release upgrade line.
1861     // Put any upgrade step following this.
1863     if ($oldversion < 2018062800.01) {
1864         // Add foreign key fk_user to the comments table.
1865         $table = new xmldb_table('comments');
1866         $key = new xmldb_key('fk_user', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));
1867         $dbman->add_key($table, $key);
1869         upgrade_main_savepoint(true, 2018062800.01);
1870     }
1872     if ($oldversion < 2018062800.02) {
1873         // Add composite index ix_concomitem to the table comments.
1874         $table = new xmldb_table('comments');
1875         $index = new xmldb_index('ix_concomitem', XMLDB_INDEX_NOTUNIQUE, array('contextid', 'commentarea', 'itemid'));
1877         if (!$dbman->index_exists($table, $index)) {
1878             $dbman->add_index($table, $index);
1879         }
1881         upgrade_main_savepoint(true, 2018062800.02);
1882     }
1884     if ($oldversion < 2018062800.03) {
1885         // Define field location to be added to event.
1886         $table = new xmldb_table('event');
1887         $field = new xmldb_field('location', XMLDB_TYPE_TEXT, null, null, null, null, null, 'priority');
1889         // Conditionally launch add field location.
1890         if (!$dbman->field_exists($table, $field)) {
1891             $dbman->add_field($table, $field);
1892         }
1894         // Main savepoint reached.
1895         upgrade_main_savepoint(true, 2018062800.03);
1896     }
1898     if ($oldversion < 2018072500.00) {
1899         // Find all duplicate top level categories per context.
1900         $duplicates = $DB->get_records_sql("SELECT qc1.*
1901                                               FROM {question_categories} qc1
1902                                               JOIN {question_categories} qc2
1903                                                 ON qc1.contextid = qc2.contextid AND qc1.id <> qc2.id
1904                                              WHERE qc1.parent = 0 AND qc2.parent = 0
1905                                           ORDER BY qc1.contextid, qc1.id");
1907         // For each context, let the first top category to remain as top category and make the rest its children.
1908         $currentcontextid = 0;
1909         $chosentopid = 0;
1910         foreach ($duplicates as $duplicate) {
1911             if ($currentcontextid != $duplicate->contextid) {
1912                 $currentcontextid = $duplicate->contextid;
1913                 $chosentopid = $duplicate->id;
1914             } else {
1915                 $DB->set_field('question_categories', 'parent', $chosentopid, ['id' => $duplicate->id]);
1916             }
1917         }
1919         // Main savepoint reached.
1920         upgrade_main_savepoint(true, 2018072500.00);
1921     }
1923     if ($oldversion < 2018073000.00) {
1924         // Main savepoint reached.
1925         if (!file_exists($CFG->dirroot . '/admin/tool/assignmentupgrade/version.php')) {
1926             unset_all_config_for_plugin('tool_assignmentupgrade');
1927         }
1928         upgrade_main_savepoint(true, 2018073000.00);
1929     }
1931     if ($oldversion < 2018083100.01) {
1932         // Remove module associated blog posts for non-existent (deleted) modules.
1933         $sql = "SELECT ba.contextid as modcontextid
1934                   FROM {blog_association} ba
1935                   JOIN {post} p
1936                        ON p.id = ba.blogid
1937              LEFT JOIN {context} c
1938                        ON c.id = ba.contextid
1939                  WHERE p.module = :module
1940                        AND c.contextlevel IS NULL
1941               GROUP BY ba.contextid";
1942         if ($deletedmodules = $DB->get_records_sql($sql, array('module' => 'blog'))) {
1943             foreach ($deletedmodules as $module) {
1944                 $assocblogids = $DB->get_fieldset_select('blog_association', 'blogid',
1945                     'contextid = :contextid', ['contextid' => $module->modcontextid]);
1946                 list($sql, $params) = $DB->get_in_or_equal($assocblogids, SQL_PARAMS_NAMED);
1948                 $DB->delete_records_select('tag_instance', "itemid $sql", $params);
1949                 $DB->delete_records_select('post', "id $sql AND module = :module",
1950                     array_merge($params, ['module' => 'blog']));
1951                 $DB->delete_records('blog_association', ['contextid' => $module->modcontextid]);
1952             }
1953         }
1955         // Main savepoint reached.
1956         upgrade_main_savepoint(true, 2018083100.01);
1957     }
1959     if ($oldversion < 2018091200.00) {
1960         if (!file_exists($CFG->dirroot . '/cache/stores/memcache/settings.php')) {
1961             unset_all_config_for_plugin('cachestore_memcache');
1962         }
1964         upgrade_main_savepoint(true, 2018091200.00);
1965     }
1967     if ($oldversion < 2018091700.01) {
1968         // Remove unused setting.
1969         unset_config('messaginghidereadnotifications');
1971         // Main savepoint reached.
1972         upgrade_main_savepoint(true, 2018091700.01);
1973     }
1975     // Add idnumber fields to question and question_category tables.
1976     // This is done in four parts to aid error recovery during upgrade, should that occur.
1977     if ($oldversion < 2018092100.01) {
1978         $table = new xmldb_table('question');
1979         $field = new xmldb_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'modifiedby');
1980         if (!$dbman->field_exists($table, $field)) {
1981             $dbman->add_field($table, $field);
1982         }
1983         upgrade_main_savepoint(true, 2018092100.01);
1984     }
1986     if ($oldversion < 2018092100.02) {
1987         $table = new xmldb_table('question');
1988         $index = new xmldb_index('categoryidnumber', XMLDB_INDEX_UNIQUE, array('category', 'idnumber'));
1989         if (!$dbman->index_exists($table, $index)) {
1990             $dbman->add_index($table, $index);
1991         }
1992         upgrade_main_savepoint(true, 2018092100.02);
1993     }
1995     if ($oldversion < 2018092100.03) {
1996         $table = new xmldb_table('question_categories');
1997         $field = new xmldb_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'sortorder');
1998         if (!$dbman->field_exists($table, $field)) {
1999             $dbman->add_field($table, $field);
2000         }
2001         upgrade_main_savepoint(true, 2018092100.03);
2002     }
2004     if ($oldversion < 2018092100.04) {
2005         $table = new xmldb_table('question_categories');
2006         $index = new xmldb_index('contextididnumber', XMLDB_INDEX_UNIQUE, array('contextid', 'idnumber'));
2007         if (!$dbman->index_exists($table, $index)) {
2008             $dbman->add_index($table, $index);
2009         }
2010         // Main savepoint reached.
2011         upgrade_main_savepoint(true, 2018092100.04);
2012     }
2014     if ($oldversion < 2018092800.00) {
2015         // Alter the table 'message_contacts'.
2016         $table = new xmldb_table('message_contacts');
2018         // Remove index so we can alter the fields.
2019         $index = new xmldb_index('userid-contactid', XMLDB_INDEX_UNIQUE, ['userid', 'contactid']);
2020         if ($dbman->index_exists($table, $index)) {
2021             $dbman->drop_index($table, $index);
2022         }
2024         // Remove defaults of '0' from the 'userid' and 'contactid' fields.
2025         $field = new xmldb_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
2026         $dbman->change_field_default($table, $field);
2028         $field = new xmldb_field('contactid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'userid');
2029         $dbman->change_field_default($table, $field);
2031         // Add the missing FKs that will now be added to new installs.
2032         $key = new xmldb_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
2033         $dbman->add_key($table, $key);
2035         $key = new xmldb_key('contactid', XMLDB_KEY_FOREIGN, ['contactid'], 'user', ['id']);
2036         $dbman->add_key($table, $key);
2038         // Re-add the index.
2039         if (!$dbman->index_exists($table, $index)) {
2040             $dbman->add_index($table, $index);
2041         }
2043         // Add the field 'timecreated'. Allow null, since existing records won't have an accurate value we can use.
2044         $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'blocked');
2045         if (!$dbman->field_exists($table, $field)) {
2046             $dbman->add_field($table, $field);
2047         }
2049         // Create new 'message_contact_requests' table.
2050         $table = new xmldb_table('message_contact_requests');
2051         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
2052         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
2053         $table->add_field('requesteduserid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'userid');
2054         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'requesteduserid');
2056         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id'], null, null);
2057         $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
2058         $table->add_key('requesteduserid', XMLDB_KEY_FOREIGN, ['requesteduserid'], 'user', ['id']);
2060         $table->add_index('userid-requesteduserid', XMLDB_INDEX_UNIQUE, ['userid', 'requesteduserid']);
2062         if (!$dbman->table_exists($table)) {
2063             $dbman->create_table($table);
2064         }
2066         // Create new 'message_users_blocked' table.
2067         $table = new xmldb_table('message_users_blocked');
2068         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null, null);
2069         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
2070         $table->add_field('blockeduserid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'userid');
2071         // Allow NULLs in the 'timecreated' field because we will be moving existing data here that has no timestamp.
2072         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'blockeduserid');
2074         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id'], null, null);
2075         $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
2076         $table->add_key('blockeduserid', XMLDB_KEY_FOREIGN, ['blockeduserid'], 'user', ['id']);
2078         $table->add_index('userid-blockeduserid', XMLDB_INDEX_UNIQUE, ['userid', 'blockeduserid']);
2080         if (!$dbman->table_exists($table)) {
2081             $dbman->create_table($table);
2082         }
2084         upgrade_main_savepoint(true, 2018092800.00);
2085     }
2087     if ($oldversion < 2018092800.01) {
2088         // Move all the 'blocked' contacts to the new table 'message_users_blocked'.
2089         $updatesql = "INSERT INTO {message_users_blocked} (userid, blockeduserid, timecreated)
2090                            SELECT userid, contactid, null as timecreated
2091                              FROM {message_contacts}
2092                             WHERE blocked = :blocked";
2093         $DB->execute($updatesql, ['blocked' => 1]);
2095         // Removed the 'blocked' column from 'message_contacts'.
2096         $table = new xmldb_table('message_contacts');
2097         $field = new xmldb_field('blocked');
2098         $dbman->drop_field($table, $field);
2100         upgrade_main_savepoint(true, 2018092800.01);
2101     }
2103     if ($oldversion < 2018092800.02) {
2104         // Delete any contacts that are not mutual (meaning they both haven't added each other).
2105         $sql = "SELECT c1.id
2106                   FROM {message_contacts} c1
2107              LEFT JOIN {message_contacts} c2
2108                     ON c1.userid = c2.contactid
2109                    AND c1.contactid = c2.userid
2110                  WHERE c2.id IS NULL";
2111         if ($contacts = $DB->get_records_sql($sql)) {
2112             list($insql, $inparams) = $DB->get_in_or_equal(array_keys($contacts));
2113             $DB->delete_records_select('message_contacts', "id $insql", $inparams);
2114         }
2116         upgrade_main_savepoint(true, 2018092800.02);
2117     }
2119     if ($oldversion < 2018092800.03) {
2120         // Remove any duplicate rows - from now on adding contacts just requires 1 row.
2121         // The person who made the contact request (userid) and the person who approved
2122         // it (contactid). Upgrade the table so that the first person to add the contact
2123         // was the one who made the request.
2124         $sql = "SELECT c1.id
2125                   FROM {message_contacts} c1
2126             INNER JOIN {message_contacts} c2
2127                     ON c1.userid = c2.contactid
2128                    AND c1.contactid = c2.userid
2129                  WHERE c1.id > c2.id";
2130         if ($contacts = $DB->get_records_sql($sql)) {
2131             list($insql, $inparams) = $DB->get_in_or_equal(array_keys($contacts));
2132             $DB->delete_records_select('message_contacts', "id $insql", $inparams);
2133         }
2135         upgrade_main_savepoint(true, 2018092800.03);
2136     }
2138     if ($oldversion < 2018101700.01) {
2139         if (empty($CFG->keepmessagingallusersenabled)) {
2140             // When it is not set, $CFG->messagingallusers should be disabled by default.
2141             // When $CFG->messagingallusers = false, the default user preference is MESSAGE_PRIVACY_COURSEMEMBER
2142             // (contacted by users sharing a course).
2143             set_config('messagingallusers', false);
2144         } else {
2145             // When $CFG->keepmessagingallusersenabled is set to true, $CFG->messagingallusers is set to true.
2146             set_config('messagingallusers', true);
2148             // When $CFG->messagingallusers = true, the default user preference is MESSAGE_PRIVACY_SITE
2149             // (contacted by all users site). So we need to set existing values from 0 (MESSAGE_PRIVACY_COURSEMEMBER)
2150             // to 2 (MESSAGE_PRIVACY_SITE).
2151             $DB->set_field(
2152                 'user_preferences',
2153                 'value',
2154                 \core_message\api::MESSAGE_PRIVACY_SITE,
2155                 array('name' => 'message_blocknoncontacts', 'value' => 0)
2156             );
2157         }
2159         // Main savepoint reached.
2160         upgrade_main_savepoint(true, 2018101700.01);
2161     }
2163     if ($oldversion < 2018101800.00) {
2164         // Define table 'favourite' to be created.
2165         $table = new xmldb_table('favourite');
2167         // Adding fields to table favourite.
2168         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2169         $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
2170         $table->add_field('itemtype', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
2171         $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2172         $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2173         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2174         $table->add_field('ordering', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2175         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2176         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2178         // Adding keys to table favourite.
2179         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2180         $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']);
2181         $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
2183         // Adding indexes to table favourite.
2184         $table->add_index('uniqueuserfavouriteitem', XMLDB_INDEX_UNIQUE, ['component', 'itemtype', 'itemid', 'contextid', 'userid']);
2186         // Conditionally launch create table for favourite.
2187         if (!$dbman->table_exists($table)) {
2188             $dbman->create_table($table);
2189         }
2191         // Main savepoint reached.
2192         upgrade_main_savepoint(true, 2018101800.00);
2193     }
2195     if ($oldversion < 2018102200.00) {
2196         // Add field 'type' to 'message_conversations'.
2197         $table = new xmldb_table('message_conversations');
2198         $field = new xmldb_field('type', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 1, 'id');
2199         if (!$dbman->field_exists($table, $field)) {
2200             $dbman->add_field($table, $field);
2201         }
2203         // Add field 'name' to 'message_conversations'.
2204         $field = new xmldb_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'type');
2205         if (!$dbman->field_exists($table, $field)) {
2206             $dbman->add_field($table, $field);
2207         }
2209         // Conditionally launch add index 'type'.
2210         $index = new xmldb_index('type', XMLDB_INDEX_NOTUNIQUE, ['type']);
2211         if (!$dbman->index_exists($table, $index)) {
2212             $dbman->add_index($table, $index);
2213         }
2215         // Define table 'message_conversations' to be updated.
2216         $table = new xmldb_table('message_conversations');
2218         // Remove the unique 'convhash' index, change to null and add a new non unique index.
2219         $index = new xmldb_index('convhash', XMLDB_INDEX_UNIQUE, ['convhash']);
2220         if ($dbman->index_exists($table, $index)) {
2221             $dbman->drop_index($table, $index);
2222         }
2224         $field = new xmldb_field('convhash', XMLDB_TYPE_CHAR, '40', null, null, null, null, 'name');
2225         $dbman->change_field_notnull($table, $field);
2227         $index = new xmldb_index('convhash', XMLDB_INDEX_NOTUNIQUE, ['convhash']);
2228         if (!$dbman->index_exists($table, $index)) {
2229             $dbman->add_index($table, $index);
2230         }
2232         upgrade_main_savepoint(true, 2018102200.00);
2233     }
2235     if ($oldversion < 2018102300.02) {
2236         // Alter 'message_conversations' table to support groups.
2237         $table = new xmldb_table('message_conversations');
2238         $field = new xmldb_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'convhash');
2239         if (!$dbman->field_exists($table, $field)) {
2240             $dbman->add_field($table, $field);
2241         }
2243         $field = new xmldb_field('itemtype', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'component');
2244         if (!$dbman->field_exists($table, $field)) {
2245             $dbman->add_field($table, $field);
2246         }
2248         $field = new xmldb_field('itemid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'itemtype');
2249         if (!$dbman->field_exists($table, $field)) {
2250             $dbman->add_field($table, $field);
2251         }
2253         $field = new xmldb_field('contextid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'itemid');
2254         if (!$dbman->field_exists($table, $field)) {
2255             $dbman->add_field($table, $field);
2256         }
2258         $field = new xmldb_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'contextid');
2259         if (!$dbman->field_exists($table, $field)) {
2260             $dbman->add_field($table, $field);
2261         }
2263         $field = new xmldb_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'enabled');
2264         if (!$dbman->field_exists($table, $field)) {
2265             $dbman->add_field($table, $field);
2266         }
2268         // Add key.
2269         $key = new xmldb_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']);
2270         $dbman->add_key($table, $key);
2272         // Add index.
2273         $index = new xmldb_index('component-itemtype-itemid-contextid', XMLDB_INDEX_NOTUNIQUE, ['component', 'itemtype',
2274             'itemid', 'contextid']);
2275         if (!$dbman->index_exists($table, $index)) {
2276             $dbman->add_index($table, $index);
2277         }
2279         upgrade_main_savepoint(true, 2018102300.02);
2280     }
2282     if ($oldversion < 2018102900.00) {
2283         // Define field predictionsprocessor to be added to analytics_models.
2284         $table = new xmldb_table('analytics_models');
2285         $field = new xmldb_field('predictionsprocessor', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'timesplitting');
2287         // Conditionally launch add field predictionsprocessor.
2288         if (!$dbman->field_exists($table, $field)) {
2289             $dbman->add_field($table, $field);
2290         }
2292         // Main savepoint reached.
2293         upgrade_main_savepoint(true, 2018102900.00);
2294     }
2296     if ($oldversion < 2018110500.01) {
2297         // Define fields to be added to the 'badge' table.
2298         $tablebadge = new xmldb_table('badge');
2299         $fieldversion = new xmldb_field('version', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'nextcron');
2300         $fieldlanguage = new xmldb_field('language', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'version');
2301         $fieldimageauthorname = new xmldb_field('imageauthorname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'language');
2302         $fieldimageauthoremail = new xmldb_field('imageauthoremail', XMLDB_TYPE_CHAR, '255', null, null,
2303             null, null, 'imageauthorname');
2304         $fieldimageauthorurl = new xmldb_field('imageauthorurl', XMLDB_TYPE_CHAR, '255', null, null,
2305             null, null, 'imageauthoremail');
2306         $fieldimagecaption = new xmldb_field('imagecaption', XMLDB_TYPE_TEXT, null, null, null, null, null, 'imageauthorurl');
2308         if (!$dbman->field_exists($tablebadge, $fieldversion)) {
2309             $dbman->add_field($tablebadge, $fieldversion);
2310         }
2311         if (!$dbman->field_exists($tablebadge, $fieldlanguage)) {
2312             $dbman->add_field($tablebadge, $fieldlanguage);
2313         }
2314         if (!$dbman->field_exists($tablebadge, $fieldimageauthorname)) {
2315             $dbman->add_field($tablebadge, $fieldimageauthorname);
2316         }
2317         if (!$dbman->field_exists($tablebadge, $fieldimageauthoremail)) {
2318             $dbman->add_field($tablebadge, $fieldimageauthoremail);
2319         }
2320         if (!$dbman->field_exists($tablebadge, $fieldimageauthorurl)) {
2321             $dbman->add_field($tablebadge, $fieldimageauthorurl);
2322         }
2323         if (!$dbman->field_exists($tablebadge, $fieldimagecaption)) {
2324             $dbman->add_field($tablebadge, $fieldimagecaption);
2325         }
2327         // Define table badge_endorsement to be created.
2328         $table = new xmldb_table('badge_endorsement');
2330         // Adding fields to table badge_endorsement.
2331         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2332         $table->add_field('badgeid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
2333         $table->add_field('issuername', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
2334         $table->add_field('issuerurl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
2335         $table->add_field('issueremail', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
2336         $table->add_field('claimid', XMLDB_TYPE_CHAR, '255', null, null, null, null);
2337         $table->add_field('claimcomment', XMLDB_TYPE_TEXT, null, null, null, null, null);
2338         $table->add_field('dateissued', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
2340         // Adding keys to table badge_endorsement.
2341         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2342         $table->add_key('endorsementbadge', XMLDB_KEY_FOREIGN, ['badgeid'], 'badge', ['id']);
2344         // Conditionally launch create table for badge_endorsement.
2345         if (!$dbman->table_exists($table)) {
2346             $dbman->create_table($table);
2347         }
2349         // Define table badge_related to be created.
2350         $table = new xmldb_table('badge_related');
2352         // Adding fields to table badge_related.
2353         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2354         $table->add_field('badgeid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
2355         $table->add_field('relatedbadgeid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2357         // Adding keys to table badge_related.
2358         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2359         $table->add_key('badgeid', XMLDB_KEY_FOREIGN, ['badgeid'], 'badge', ['id']);
2360         $table->add_key('relatedbadgeid', XMLDB_KEY_FOREIGN, ['relatedbadgeid'], 'badge', ['id']);
2361         $table->add_key('badgeid-relatedbadgeid', XMLDB_KEY_UNIQUE, ['badgeid', 'relatedbadgeid']);
2363         // Conditionally launch create table for badge_related.
2364         if (!$dbman->table_exists($table)) {
2365             $dbman->create_table($table);
2366         }
2368         // Define table badge_competencies to be created.
2369         $table = new xmldb_table('badge_competencies');
2371         // Adding fields to table badge_competencies.
2372         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2373         $table->add_field('badgeid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
2374         $table->add_field('targetname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
2375         $table->add_field('targeturl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
2376         $table->add_field('targetdescription', XMLDB_TYPE_TEXT, null, null, null, null, null);
2377         $table->add_field('targetframework', XMLDB_TYPE_CHAR, '255', null, null, null, null);
2378         $table->add_field('targetcode', XMLDB_TYPE_CHAR, '255', null, null, null, null);
2380         // Adding keys to table badge_competencies.
2381         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2382         $table->add_key('competenciesbadge', XMLDB_KEY_FOREIGN, ['badgeid'], 'badge', ['id']);
2384         // Conditionally launch create table for badge_competencies.
2385         if (!$dbman->table_exists($table)) {
2386             $dbman->create_table($table);
2387         }
2389         // Main savepoint reached.
2390         upgrade_main_savepoint(true, 2018110500.01);
2391     }
2393     if ($oldversion < 2018110700.01) {
2394         // This config setting added and then removed.
2395         unset_config('showcourseimages', 'moodlecourse');
2397         // Main savepoint reached.
2398         upgrade_main_savepoint(true, 2018110700.01);
2399     }
2401     if ($oldversion < 2018111301.00) {
2402         // Define field locked to be added to context.
2403         $table = new xmldb_table('context');
2404         $field = new xmldb_field('locked', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'depth');
2406         // Conditionally launch add field locked.
2407         if (!$dbman->field_exists($table, $field)) {
2408             $dbman->add_field($table, $field);
2409         }
2411         // Define field locked to be added to context_temp.
2412         $table = new xmldb_table('context_temp');
2413         $field = new xmldb_field('locked', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'depth');
2415         // Conditionally launch add field locked.
2416         if (!$dbman->field_exists($table, $field)) {
2417             $dbman->add_field($table, $field);
2418         }
2420         // Note: This change also requires a bump in is_major_upgrade_required.
2421         upgrade_main_savepoint(true, 2018111301.00);
2422     }
2424     if ($oldversion < 2018111900.00) {
2425         // Update favourited courses, so they are saved in the particular course context instead of the system.
2426         $favouritedcourses = $DB->get_records('favourite', ['component' => 'core_course', 'itemtype' => 'courses']);
2428         foreach ($favouritedcourses as $fc) {
2429             $coursecontext = \context_course::instance($fc->itemid);
2430             $fc->contextid = $coursecontext->id;
2431             $DB->update_record('favourite', $fc);
2432         }
2434         upgrade_main_savepoint(true, 2018111900.00);
2435     }
2437     if ($oldversion < 2018111900.01) {
2438         // Define table oauth2_access_token to be created.
2439         $table = new xmldb_table('oauth2_access_token');
2441         // Adding fields to table oauth2_access_token.
2442         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2443         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2444         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2445         $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2446         $table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2447         $table->add_field('token', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
2448         $table->add_field('expires', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2449         $table->add_field('scope', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
2451         // Adding keys to table oauth2_access_token.
2452         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2453         $table->add_key('issueridkey', XMLDB_KEY_FOREIGN_UNIQUE, ['issuerid'], 'oauth2_issuer', ['id']);
2455         // Conditionally launch create table for oauth2_access_token.
2456         if (!$dbman->table_exists($table)) {
2457             $dbman->create_table($table);
2458         }
2460         // Main savepoint reached.
2461         upgrade_main_savepoint(true, 2018111900.01);
2462     }
2464     if ($oldversion < 2018112000.00) {
2465         // Update favourited conversations, so they are saved in the proper context instead of the system.
2466         $sql = "SELECT f.*, mc.contextid as conversationctx
2467                   FROM {favourite} f
2468                   JOIN {message_conversations} mc
2469                     ON mc.id = f.itemid";
2470         $favouritedconversations = $DB->get_records_sql($sql);
2471         foreach ($favouritedconversations as $fc) {
2472             if (empty($fc->conversationctx)) {
2473                 $conversationidctx = \context_user::instance($fc->userid)->id;
2474             } else {
2475                 $conversationidctx = $fc->conversationctx;
2476             }
2478             $DB->set_field('favourite', 'contextid', $conversationidctx, ['id' => $fc->id]);
2479         }
2481         upgrade_main_savepoint(true, 2018112000.00);
2482     }
2484     // Automatically generated Moodle v3.6.0 release upgrade line.
2485     // Put any upgrade step following this.
2487     if ($oldversion < 2018120300.01) {
2488         // Update the FB logo URL.
2489         $oldurl = 'https://facebookbrand.com/wp-content/themes/fb-branding/prj-fb-branding/assets/images/fb-art.png';
2490         $newurl = 'https://facebookbrand.com/wp-content/uploads/2016/05/flogo_rgb_hex-brc-site-250.png';
2492         $updatesql = "UPDATE {oauth2_issuer}
2493                          SET image = :newimage
2494                        WHERE " . $DB->sql_compare_text('image', 100). " = :oldimage";
2495         $params = [
2496             'newimage' => $newurl,
2497             'oldimage' => $oldurl
2498         ];
2499         $DB->execute($updatesql, $params);
2501         upgrade_main_savepoint(true, 2018120300.01);
2502     }
2504     if ($oldversion < 2018120300.02) {
2505         // Set all individual conversations to enabled.
2506         $updatesql = "UPDATE {message_conversations}
2507                          SET enabled = :enabled
2508                        WHERE type = :type";
2509         $DB->execute($updatesql, ['enabled' => 1, 'type' => 1]);
2511         upgrade_main_savepoint(true, 2018120300.02);
2512     }
2514     if ($oldversion < 2018120301.02) {
2515         upgrade_delete_orphaned_file_records();
2516         upgrade_main_savepoint(true, 2018120301.02);
2517     }
2519     if ($oldversion < 2019011500.00) {
2520         // Define table task_log to be created.
2521         $table = new xmldb_table('task_log');
2523         // Adding fields to table task_log.
2524         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2525         $table->add_field('type', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null);
2526         $table->add_field('component', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
2527         $table->add_field('classname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
2528         $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2529         $table->add_field('timestart', XMLDB_TYPE_NUMBER, '20, 10', null, XMLDB_NOTNULL, null, null);
2530         $table->add_field('timeend', XMLDB_TYPE_NUMBER, '20, 10', null, XMLDB_NOTNULL, null, null);
2531         $table->add_field('dbreads', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2532         $table->add_field('dbwrites', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2533         $table->add_field('result', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, null);
2535         // Adding keys to table task_log.
2536         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2538         // Adding indexes to table task_log.
2539         $table->add_index('classname', XMLDB_INDEX_NOTUNIQUE, ['classname']);
2540         $table->add_index('timestart', XMLDB_INDEX_NOTUNIQUE, ['timestart']);
2542         // Conditionally launch create table for task_log.
2543         if (!$dbman->table_exists($table)) {
2544             $dbman->create_table($table);
2545         }
2547         // Main savepoint reached.
2548         upgrade_main_savepoint(true, 2019011500.00);
2549     }
2551     if ($oldversion < 2019011501.00) {
2552         // Define field output to be added to task_log.
2553         $table = new xmldb_table('task_log');
2554         $field = new xmldb_field('output', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null, 'result');
2556         // Conditionally launch add field output.
2557         if (!$dbman->field_exists($table, $field)) {
2558             $dbman->add_field($table, $field);
2559         }
2561         // Main savepoint reached.
2562         upgrade_main_savepoint(true, 2019011501.00);
2563     }
2565     if ($oldversion < 2019011801.00) {
2567         // Define table customfield_category to be created.
2568         $table = new xmldb_table('customfield_category');
2570         // Adding fields to table customfield_category.
2571         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2572         $table->add_field('name', XMLDB_TYPE_CHAR, '400', null, XMLDB_NOTNULL, null, null);
2573         $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null);
2574         $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2575         $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2576         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2577         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2578         $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
2579         $table->add_field('area', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
2580         $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
2581         $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2583         // Adding keys to table customfield_category.
2584         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2585         $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']);
2587         // Adding indexes to table customfield_category.
2588         $table->add_index('component_area_itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'area', 'itemid', 'sortorder']);
2590         // Conditionally launch create table for customfield_category.
2591         if (!$dbman->table_exists($table)) {
2592             $dbman->create_table($table);
2593         }
2595         // Define table customfield_field to be created.
2596         $table = new xmldb_table('customfield_field');
2598         // Adding fields to table customfield_field.
2599         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2600         $table->add_field('shortname', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
2601         $table->add_field('name', XMLDB_TYPE_CHAR, '400', null, XMLDB_NOTNULL, null, null);
2602         $table->add_field('type', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
2603         $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null);
2604         $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2605         $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2606         $table->add_field('categoryid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2607         $table->add_field('configdata', XMLDB_TYPE_TEXT, null, null, null, null, null);
2608         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2609         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2611         // Adding keys to table customfield_field.
2612         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2613         $table->add_key('categoryid', XMLDB_KEY_FOREIGN, ['categoryid'], 'customfield_category', ['id']);
2615         // Adding indexes to table customfield_field.
2616         $table->add_index('categoryid_sortorder', XMLDB_INDEX_NOTUNIQUE, ['categoryid', 'sortorder']);
2618         // Conditionally launch create table for customfield_field.
2619         if (!$dbman->table_exists($table)) {
2620             $dbman->create_table($table);
2621         }
2623         // Define table customfield_data to be created.
2624         $table = new xmldb_table('customfield_data');
2626         // Adding fields to table customfield_data.
2627         $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2628         $table->add_field('fieldid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2629         $table->add_field('instanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2630         $table->add_field('intvalue', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2631         $table->add_field('decvalue', XMLDB_TYPE_NUMBER, '10, 5', null, null, null, null);
2632         $table->add_field('shortcharvalue', XMLDB_TYPE_CHAR, '255', null, null, null, null);
2633         $table->add_field('charvalue', XMLDB_TYPE_CHAR, '1333', null, null, null, null);
2634         $table->add_field('value', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
2635         $table->add_field('valueformat', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2636         $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2637         $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2638         $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2640         // Adding keys to table customfield_data.
2641         $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2642         $table->add_key('fieldid', XMLDB_KEY_FOREIGN, ['fieldid'], 'customfield_field', ['id']);
2643         $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']);
2645         // Adding indexes to table customfield_data.
2646         $table->add_index('instanceid-fieldid', XMLDB_INDEX_UNIQUE, ['instanceid', 'fieldid']);
2647         $table->add_index('fieldid-intvalue', XMLDB_INDEX_NOTUNIQUE, ['fieldid', 'intvalue']);
2648         $table->add_index('fieldid-shortcharvalue', XMLDB_INDEX_NOTUNIQUE, ['fieldid', 'shortcharvalue']);
2649         $table->add_index('fieldid-decvalue', XMLDB_INDEX_NOTUNIQUE, ['fieldid', 'decvalue']);
2651         // Conditionally launch create table for customfield_data.
2652         if (!$dbman->table_exists($table)) {
2653             $dbman->create_table($table);
2654         }
2656         upgrade_main_savepoint(true, 2019011801.00);
2657     }
2659     if ($oldversion < 2019011801.01) {
2661         // Delete all files that have been used in sections, which are already deleted.
2662         $sql = "SELECT DISTINCT f.itemid as sectionid, f.contextid
2663                   FROM {files} f
2664              LEFT JOIN {course_sections} s ON f.itemid = s.id
2665                  WHERE f.component = :component AND f.filearea = :filearea AND s.id IS NULL ";
2667         $params = [
2668             'component' => 'course',
2669             'filearea' => 'section'
2670         ];
2672         $stalefiles = $DB->get_recordset_sql($sql, $params);
2674         $fs = get_file_storage();
2675         foreach ($stalefiles as $stalefile) {
2676             $fs->delete_area_files($stalefile->contextid, 'course', 'section', $stalefile->sectionid);
2677         }
2678         $stalefiles->close();
2680         upgrade_main_savepoint(true, 2019011801.01);
2681     }
2683     if ($oldversion < 2019011801.02) {
2684         // Add index 'useridfrom' to the table 'notifications'.
2685         $table = new xmldb_table('notifications');
2686         $index = new xmldb_index('useridfrom', XMLDB_INDEX_NOTUNIQUE, ['useridfrom']);
2688         if (!$dbman->index_exists($table, $index)) {
2689             $dbman->add_index($table, $index);
2690         }
2692         upgrade_main_savepoint(true, 2019011801.02);
2693     }
2695     if ($oldversion < 2019011801.03) {
2696         // Remove duplicate entries from group memberships.
2697         // Find records with multiple userid/groupid combinations and find the highest ID.
2698         // Later we will remove all those entries.
2699         $sql = "
2700             SELECT MIN(id) as minid, userid, groupid
2701             FROM {groups_members}
2702             GROUP BY userid, groupid
2703             HAVING COUNT(id) > 1";
2704         if ($duplicatedrows = $DB->get_recordset_sql($sql)) {
2705             foreach ($duplicatedrows as $row) {
2706                 $DB->delete_records_select('groups_members',
2707                     'userid = :userid AND groupid = :groupid AND id <> :minid', (array)$row);
2708             }
2709         }
2710         $duplicatedrows->close();
2712         // Define key useridgroupid (unique) to be added to group_members.
2713         $table = new xmldb_table('groups_members');
2714         $key = new xmldb_key('useridgroupid', XMLDB_KEY_UNIQUE, array('userid', 'groupid'));
2715         // Launch add key useridgroupid.
2716         $dbman->add_key($table, $key);
2718         // Main savepoint reached.
2719         upgrade_main_savepoint(true, 2019011801.03);
2720     }
2722     return true;