weekly release 4.0dev
[moodle.git] / lib / db / upgrade.php
CommitLineData
5b4a78e2 1<?php
5b4a78e2 2// This file is part of Moodle - http://moodle.org/
4e423cbf 3//
5b4a78e2
PS
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.
4e423cbf 8//
5b4a78e2
PS
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.
4e423cbf 13//
5b4a78e2
PS
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/>.
16
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 *
39b90b51
EL
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
5b4a78e2
PS
41 */
42
43defined('MOODLE_INTERNAL') || die();
4e423cbf 44
3406acde 45/**
39b90b51
EL
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
f9488a6f 49 * version is detected. It's in charge of performing the required tasks
39b90b51
EL
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",
f9488a6f 53 * each one performing one isolated (from the rest of steps) task. Usually
39b90b51
EL
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) {
f9488a6f 60 * // Explanation of the update step, linking to issue in the Tracker if necessary
39b90b51
EL
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
f9488a6f 77 * that such a file must be manually included from upgrade.php, and there are some restrictions
39b90b51
EL
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}
3406acde 83 *
3406acde 84 * @param int $oldversion
5b4a78e2 85 * @return bool always true
3406acde 86 */
775f811a 87function xmldb_main_upgrade($oldversion) {
e8c82aac 88 global $CFG, $DB;
4e423cbf 89
e8c82aac 90 require_once($CFG->libdir.'/db/upgradelib.php'); // Core Upgrade-related functions.
13a0d3d3 91
e8c82aac 92 $dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes.
f33e1ed4 93
e8c82aac 94 // Always keep this upgrade step with version being the minimum
77342b96
EL
95 // allowed version to upgrade from (v3.6.0 right now).
96 if ($oldversion < 2018120300) {
e8c82aac 97 // Just in case somebody hacks upgrade scripts or env, we really can not continue.
77342b96 98 echo("You need to upgrade to 3.6.x or higher first!\n");
5c79b8ed 99 exit(1);
e8c82aac 100 // Note this savepoint is 100% unreachable, but needed to pass the upgrade checks.
77342b96 101 upgrade_main_savepoint(true, 2018120300);
6b036d04
SA
102 }
103
f47c8f35
EL
104 // Automatically generated Moodle v3.6.0 release upgrade line.
105 // Put any upgrade step following this.
106
4b0cf053
MN
107 if ($oldversion < 2018120300.01) {
108 // Update the FB logo URL.
109 $oldurl = 'https://facebookbrand.com/wp-content/themes/fb-branding/prj-fb-branding/assets/images/fb-art.png';
110 $newurl = 'https://facebookbrand.com/wp-content/uploads/2016/05/flogo_rgb_hex-brc-site-250.png';
111
112 $updatesql = "UPDATE {oauth2_issuer}
113 SET image = :newimage
607a6ca9 114 WHERE " . $DB->sql_compare_text('image', 100). " = :oldimage";
4b0cf053
MN
115 $params = [
116 'newimage' => $newurl,
117 'oldimage' => $oldurl
118 ];
119 $DB->execute($updatesql, $params);
120
121 upgrade_main_savepoint(true, 2018120300.01);
122 }
123
7bb22a29
MN
124 if ($oldversion < 2018120300.02) {
125 // Set all individual conversations to enabled.
126 $updatesql = "UPDATE {message_conversations}
127 SET enabled = :enabled
128 WHERE type = :type";
129 $DB->execute($updatesql, ['enabled' => 1, 'type' => 1]);
130
131 upgrade_main_savepoint(true, 2018120300.02);
132 }
133
f408e1f8
IT
134 if ($oldversion < 2018120301.02) {
135 upgrade_delete_orphaned_file_records();
136 upgrade_main_savepoint(true, 2018120301.02);
137 }
138
af540d42
AN
139 if ($oldversion < 2019011500.00) {
140 // Define table task_log to be created.
141 $table = new xmldb_table('task_log');
142
143 // Adding fields to table task_log.
144 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
145 $table->add_field('type', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null);
146 $table->add_field('component', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
147 $table->add_field('classname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
148 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
149 $table->add_field('timestart', XMLDB_TYPE_NUMBER, '20, 10', null, XMLDB_NOTNULL, null, null);
150 $table->add_field('timeend', XMLDB_TYPE_NUMBER, '20, 10', null, XMLDB_NOTNULL, null, null);
151 $table->add_field('dbreads', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
152 $table->add_field('dbwrites', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
153 $table->add_field('result', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, null);
154
155 // Adding keys to table task_log.
156 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
157
158 // Adding indexes to table task_log.
159 $table->add_index('classname', XMLDB_INDEX_NOTUNIQUE, ['classname']);
160 $table->add_index('timestart', XMLDB_INDEX_NOTUNIQUE, ['timestart']);
161
162 // Conditionally launch create table for task_log.
163 if (!$dbman->table_exists($table)) {
164 $dbman->create_table($table);
165 }
166
167 // Main savepoint reached.
168 upgrade_main_savepoint(true, 2019011500.00);
169 }
170
4b71596f
AN
171 if ($oldversion < 2019011501.00) {
172 // Define field output to be added to task_log.
173 $table = new xmldb_table('task_log');
174 $field = new xmldb_field('output', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null, 'result');
175
176 // Conditionally launch add field output.
177 if (!$dbman->field_exists($table, $field)) {
178 $dbman->add_field($table, $field);
179 }
180
181 // Main savepoint reached.
182 upgrade_main_savepoint(true, 2019011501.00);
183 }
184
1eeb465a
TBM
185 if ($oldversion < 2019011801.00) {
186
187 // Define table customfield_category to be created.
188 $table = new xmldb_table('customfield_category');
189
190 // Adding fields to table customfield_category.
191 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
192 $table->add_field('name', XMLDB_TYPE_CHAR, '400', null, XMLDB_NOTNULL, null, null);
193 $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null);
194 $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
195 $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
196 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
197 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
198 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
199 $table->add_field('area', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
200 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
201 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
202
203 // Adding keys to table customfield_category.
204 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
205 $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']);
206
207 // Adding indexes to table customfield_category.
208 $table->add_index('component_area_itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'area', 'itemid', 'sortorder']);
209
210 // Conditionally launch create table for customfield_category.
211 if (!$dbman->table_exists($table)) {
212 $dbman->create_table($table);
213 }
214
215 // Define table customfield_field to be created.
216 $table = new xmldb_table('customfield_field');
217
218 // Adding fields to table customfield_field.
219 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
220 $table->add_field('shortname', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
221 $table->add_field('name', XMLDB_TYPE_CHAR, '400', null, XMLDB_NOTNULL, null, null);
222 $table->add_field('type', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
223 $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null);
224 $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
225 $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
226 $table->add_field('categoryid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
227 $table->add_field('configdata', XMLDB_TYPE_TEXT, null, null, null, null, null);
228 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
229 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
230
231 // Adding keys to table customfield_field.
232 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
233 $table->add_key('categoryid', XMLDB_KEY_FOREIGN, ['categoryid'], 'customfield_category', ['id']);
234
235 // Adding indexes to table customfield_field.
236 $table->add_index('categoryid_sortorder', XMLDB_INDEX_NOTUNIQUE, ['categoryid', 'sortorder']);
237
238 // Conditionally launch create table for customfield_field.
239 if (!$dbman->table_exists($table)) {
240 $dbman->create_table($table);
241 }
242
243 // Define table customfield_data to be created.
244 $table = new xmldb_table('customfield_data');
245
246 // Adding fields to table customfield_data.
247 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
248 $table->add_field('fieldid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
249 $table->add_field('instanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
250 $table->add_field('intvalue', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
251 $table->add_field('decvalue', XMLDB_TYPE_NUMBER, '10, 5', null, null, null, null);
252 $table->add_field('shortcharvalue', XMLDB_TYPE_CHAR, '255', null, null, null, null);
253 $table->add_field('charvalue', XMLDB_TYPE_CHAR, '1333', null, null, null, null);
254 $table->add_field('value', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
255 $table->add_field('valueformat', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
256 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
257 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
258 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
259
260 // Adding keys to table customfield_data.
261 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
262 $table->add_key('fieldid', XMLDB_KEY_FOREIGN, ['fieldid'], 'customfield_field', ['id']);
263 $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']);
264
265 // Adding indexes to table customfield_data.
266 $table->add_index('instanceid-fieldid', XMLDB_INDEX_UNIQUE, ['instanceid', 'fieldid']);
267 $table->add_index('fieldid-intvalue', XMLDB_INDEX_NOTUNIQUE, ['fieldid', 'intvalue']);
268 $table->add_index('fieldid-shortcharvalue', XMLDB_INDEX_NOTUNIQUE, ['fieldid', 'shortcharvalue']);
269 $table->add_index('fieldid-decvalue', XMLDB_INDEX_NOTUNIQUE, ['fieldid', 'decvalue']);
270
271 // Conditionally launch create table for customfield_data.
272 if (!$dbman->table_exists($table)) {
273 $dbman->create_table($table);
274 }
275
276 upgrade_main_savepoint(true, 2019011801.00);
277 }
278
85e62192 279 if ($oldversion < 2019011801.01) {
d5ef6852
AW
280
281 // Delete all files that have been used in sections, which are already deleted.
282 $sql = "SELECT DISTINCT f.itemid as sectionid, f.contextid
283 FROM {files} f
284 LEFT JOIN {course_sections} s ON f.itemid = s.id
285 WHERE f.component = :component AND f.filearea = :filearea AND s.id IS NULL ";
286
287 $params = [
288 'component' => 'course',
289 'filearea' => 'section'
290 ];
291
292 $stalefiles = $DB->get_recordset_sql($sql, $params);
293
294 $fs = get_file_storage();
295 foreach ($stalefiles as $stalefile) {
296 $fs->delete_area_files($stalefile->contextid, 'course', 'section', $stalefile->sectionid);
297 }
298 $stalefiles->close();
299
85e62192 300 upgrade_main_savepoint(true, 2019011801.01);
d5ef6852
AW
301 }
302
c5944a1d
DM
303 if ($oldversion < 2019011801.02) {
304 // Add index 'useridfrom' to the table 'notifications'.
305 $table = new xmldb_table('notifications');
306 $index = new xmldb_index('useridfrom', XMLDB_INDEX_NOTUNIQUE, ['useridfrom']);
307
308 if (!$dbman->index_exists($table, $index)) {
309 $dbman->add_index($table, $index);
310 }
311
312 upgrade_main_savepoint(true, 2019011801.02);
313 }
314
8516febd
JD
315 if ($oldversion < 2019011801.03) {
316 // Remove duplicate entries from group memberships.
317 // Find records with multiple userid/groupid combinations and find the highest ID.
318 // Later we will remove all those entries.
319 $sql = "
320 SELECT MIN(id) as minid, userid, groupid
321 FROM {groups_members}
322 GROUP BY userid, groupid
323 HAVING COUNT(id) > 1";
324 if ($duplicatedrows = $DB->get_recordset_sql($sql)) {
325 foreach ($duplicatedrows as $row) {
326 $DB->delete_records_select('groups_members',
327 'userid = :userid AND groupid = :groupid AND id <> :minid', (array)$row);
328 }
329 }
330 $duplicatedrows->close();
331
332 // Define key useridgroupid (unique) to be added to group_members.
333 $table = new xmldb_table('groups_members');
334 $key = new xmldb_key('useridgroupid', XMLDB_KEY_UNIQUE, array('userid', 'groupid'));
335 // Launch add key useridgroupid.
336 $dbman->add_key($table, $key);
8516febd
JD
337 // Main savepoint reached.
338 upgrade_main_savepoint(true, 2019011801.03);
339 }
340
b5b112f6
DM
341 if ($oldversion < 2019021500.01) {
342 $insights = $DB->get_record('message_providers', ['component' => 'moodle', 'name' => 'insights']);
6d6a83e9
AG
343 if (!empty($insights)) {
344 $insights->capability = null;
345 $DB->update_record('message_providers', $insights);
346 }
b5b112f6
DM
347 upgrade_main_savepoint(true, 2019021500.01);
348 }
349
df4a17c7 350 if ($oldversion < 2019021500.02) {
46014b83
MN
351 // Default 'off' for existing sites as this is the behaviour they had earlier.
352 set_config('messagingdefaultpressenter', false);
353
354 // Main savepoint reached.
df4a17c7 355 upgrade_main_savepoint(true, 2019021500.02);
46014b83
MN
356 }
357
05506ead 358 if ($oldversion < 2019030100.01) {
2085e860
DM
359 // Create adhoc task to delete renamed My Course search area (ID core_course-mycourse).
360 $record = new \stdClass();
361 $record->classname = '\core\task\clean_up_deleted_search_area_task';
362 $record->component = 'core';
363
364 // Next run time based from nextruntime computation in \core\task\manager::queue_adhoc_task().
365 $nextruntime = time() - 1;
366 $record->nextruntime = $nextruntime;
367 $record->customdata = json_encode('core_course-mycourse');
368
369 $DB->insert_record('task_adhoc', $record);
370
371 // Main savepoint reached.
05506ead 372 upgrade_main_savepoint(true, 2019030100.01);
2085e860
DM
373 }
374
e97dfff7
DM
375 if ($oldversion < 2019030700.01) {
376
377 // Define field evaluationmode to be added to analytics_models_log.
378 $table = new xmldb_table('analytics_models_log');
379 $field = new xmldb_field('evaluationmode', XMLDB_TYPE_CHAR, '50', null, null, null,
380 null, 'version');
381
382 // Conditionally launch add field evaluationmode.
383 if (!$dbman->field_exists($table, $field)) {
384 $dbman->add_field($table, $field);
385
386 $updatesql = "UPDATE {analytics_models_log}
387 SET evaluationmode = 'configuration'";
388 $DB->execute($updatesql, []);
389
390 // Changing nullability of field evaluationmode on table block_instances to not null.
391 $field = new xmldb_field('evaluationmode', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL,
392 null, null, 'version');
393
394 // Launch change of nullability for field evaluationmode.
395 $dbman->change_field_notnull($table, $field);
396 }
397
398 // Main savepoint reached.
399 upgrade_main_savepoint(true, 2019030700.01);
400 }
401
1fadad46
MN
402 if ($oldversion < 2019030800.00) {
403 // Define table 'message_conversation_actions' to be created.
404 // Note - I would have preferred 'message_conversation_user_actions' but due to Oracle we can't. Boo.
405 $table = new xmldb_table('message_conversation_actions');
406
407 // Adding fields to table 'message_conversation_actions'.
408 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
409 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
410 $table->add_field('conversationid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
411 $table->add_field('action', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
412 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
413
414 // Adding keys to table 'message_conversation_actions'.
415 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
416 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
417 $table->add_key('conversationid', XMLDB_KEY_FOREIGN, ['conversationid'], 'message_conversations', ['id']);
418
419 // Conditionally launch create table for 'message_conversation_actions'.
420 if (!$dbman->table_exists($table)) {
421 $dbman->create_table($table);
422 }
423
424 // Main savepoint reached.
425 upgrade_main_savepoint(true, 2019030800.00);
426 }
427
07a4698d
MN
428 if ($oldversion < 2019030800.02) {
429 // Remove any conversations and their members associated with non-existent groups.
430 $sql = "SELECT mc.id
431 FROM {message_conversations} mc
432 LEFT JOIN {groups} g
433 ON mc.itemid = g.id
434 WHERE mc.component = :component
435 AND mc.itemtype = :itemtype
436 AND g.id is NULL";
437 $conversations = $DB->get_records_sql($sql, ['component' => 'core_group', 'itemtype' => 'groups']);
438
439 if ($conversations) {
440 $conversationids = array_keys($conversations);
441
442 $DB->delete_records_list('message_conversations', 'id', $conversationids);
443 $DB->delete_records_list('message_conversation_members', 'conversationid', $conversationids);
444 $DB->delete_records_list('message_conversation_actions', 'conversationid', $conversationids);
445
446 // Now, go through each conversation and delete any messages and related message actions.
447 foreach ($conversationids as $conversationid) {
448 if ($messages = $DB->get_records('messages', ['conversationid' => $conversationid])) {
449 $messageids = array_keys($messages);
450
451 // Delete the actions.
452 list($insql, $inparams) = $DB->get_in_or_equal($messageids);
453 $DB->delete_records_select('message_user_actions', "messageid $insql", $inparams);
454
455 // Delete the messages.
456 $DB->delete_records('messages', ['conversationid' => $conversationid]);
457 }
458 }
459 }
460
461 // Main savepoint reached.
462 upgrade_main_savepoint(true, 2019030800.02);
463 }
464
bd9fb479
EL
465 if ($oldversion < 2019030800.03) {
466
9b3580f4
DM
467 // Add missing indicators to course_dropout.
468 $params = [
469 'target' => '\core\analytics\target\course_dropout',
470 'trained' => 0,
471 'enabled' => 0,
472 ];
473 $models = $DB->get_records('analytics_models', $params);
474 foreach ($models as $model) {
475 $indicators = json_decode($model->indicators);
476
477 $potentiallymissingindicators = [
478 '\core_course\analytics\indicator\completion_enabled',
479 '\core_course\analytics\indicator\potential_cognitive_depth',
480 '\core_course\analytics\indicator\potential_social_breadth',
481 '\core\analytics\indicator\any_access_after_end',
482 '\core\analytics\indicator\any_access_before_start',
483 '\core\analytics\indicator\any_write_action_in_course',
484 '\core\analytics\indicator\read_actions'
485 ];
486
487 $missing = false;
488 foreach ($potentiallymissingindicators as $potentiallymissingindicator) {
489 if (!in_array($potentiallymissingindicator, $indicators)) {
490 // Add the missing indicator to sites upgraded before 2017072000.02.
491 $indicators[] = $potentiallymissingindicator;
492 $missing = true;
493 }
494 }
495
496 if ($missing) {
497 $model->indicators = json_encode($indicators);
498 $model->version = time();
499 $model->timemodified = time();
500 $DB->update_record('analytics_models', $model);
501 }
502 }
503
504 // Add missing indicators to no_teaching.
505 $params = [
506 'target' => '\core\analytics\target\no_teaching',
507 ];
508 $models = $DB->get_records('analytics_models', $params);
509 foreach ($models as $model) {
510 $indicators = json_decode($model->indicators);
511 if (!in_array('\core_course\analytics\indicator\no_student', $indicators)) {
512 // Add the missing indicator to sites upgraded before 2017072000.02.
513
514 $indicators[] = '\core_course\analytics\indicator\no_student';
515
516 $model->indicators = json_encode($indicators);
517 $model->version = time();
518 $model->timemodified = time();
519 $DB->update_record('analytics_models', $model);
520 }
521 }
522
523 // Main savepoint reached.
bd9fb479 524 upgrade_main_savepoint(true, 2019030800.03);
9b3580f4
DM
525 }
526
3576b66b
DM
527 if ($oldversion < 2019031500.01) {
528
529 $defaulttimesplittings = get_config('analytics', 'timesplittings');
530 if ($defaulttimesplittings !== false) {
531 set_config('defaulttimesplittingsevaluation', $defaulttimesplittings, 'analytics');
532 unset_config('timesplittings', 'analytics');
533 }
534
535 // Main savepoint reached.
536 upgrade_main_savepoint(true, 2019031500.01);
537 }
538
340f5c9e 539 if ($oldversion < 2019032200.02) {
b29cfc58
DM
540 // The no_teaching model might have been marked as not-trained by mistake (static models are always trained).
541 $DB->set_field('analytics_models', 'trained', 1, ['target' => '\core\analytics\target\no_teaching']);
340f5c9e 542 upgrade_main_savepoint(true, 2019032200.02);
b29cfc58
DM
543 }
544
e8bfd9b4
DW
545 if ($oldversion < 2019032900.00) {
546
547 // Define table badge_competencies to be renamed to badge_alignment.
548 $table = new xmldb_table('badge_competencies');
549
550 // Be careful if this step gets run twice.
551 if ($dbman->table_exists($table)) {
552 $key = new xmldb_key('competenciesbadge', XMLDB_KEY_FOREIGN, ['badgeid'], 'badge', ['id']);
553
554 // Launch drop key competenciesbadge.
555 $dbman->drop_key($table, $key);
556
557 $key = new xmldb_key('alignmentsbadge', XMLDB_KEY_FOREIGN, ['badgeid'], 'badge', ['id']);
558
559 // Launch add key alignmentsbadge.
560 $dbman->add_key($table, $key);
561
562 // Launch rename table for badge_alignment.
563 $dbman->rename_table($table, 'badge_alignment');
564 }
565
566 upgrade_main_savepoint(true, 2019032900.00);
567 }
568
d15b5340 569 if ($oldversion < 2019032900.01) {
5a01c240
SL
570 $sql = "UPDATE {task_scheduled}
571 SET classname = ?
572 WHERE component = ?
573 AND classname = ?";
574 $DB->execute($sql, [
575 '\core\task\question_preview_cleanup_task',
576 'moodle',
577 '\core\task\question_cron_task'
578 ]);
579
580 // Main savepoint reached.
d15b5340 581 upgrade_main_savepoint(true, 2019032900.01);
0e133245
MM
582 }
583
584 if ($oldversion < 2019040200.01) {
585 // Removing the themes BSB, Clean, More from core.
586 // If these theme wish to be retained empty this array before upgrade.
587 $themes = array('theme_bootstrapbase' => 'bootstrapbase',
588 'theme_clean' => 'clean', 'theme_more' => 'more');
589 foreach ($themes as $key => $theme) {
590 if (check_dir_exists($CFG->dirroot . '/theme/' . $theme, false)) {
591 // Ignore the themes that have been re-downloaded.
592 unset($themes[$key]);
593 }
594 }
595 // Check we actually have themes to remove.
596 if (count($themes) > 0) {
597 list($insql, $inparams) = $DB->get_in_or_equal($themes, SQL_PARAMS_NAMED);
598
599 // Replace the theme usage.
600 $DB->set_field_select('course', 'theme', 'classic', "theme $insql", $inparams);
601 $DB->set_field_select('course_categories', 'theme', 'classic', "theme $insql", $inparams);
602 $DB->set_field_select('user', 'theme', 'classic', "theme $insql", $inparams);
603 $DB->set_field_select('mnet_host', 'theme', 'classic', "theme $insql", $inparams);
604 $DB->set_field_select('cohort', 'theme', 'classic', "theme $insql", $inparams);
605
606 // Replace the theme configs.
607 if (in_array(get_config('core', 'theme'), $themes)) {
608 set_config('theme', 'classic');
609 }
610 if (in_array(get_config('core', 'thememobile'), $themes)) {
611 set_config('thememobile', 'classic');
612 }
613 if (in_array(get_config('core', 'themelegacy'), $themes)) {
614 set_config('themelegacy', 'classic');
615 }
616 if (in_array(get_config('core', 'themetablet'), $themes)) {
617 set_config('themetablet', 'classic');
618 }
619
620 // Hacky emulation of plugin uninstallation.
621 foreach ($themes as $key => $theme) {
622 unset_all_config_for_plugin($key);
623 }
624 }
625
626 // Main savepoint reached.
627 upgrade_main_savepoint(true, 2019040200.01);
5a01c240
SL
628 }
629
9f690999
DM
630 if ($oldversion < 2019040600.02) {
631
632 // Define key fileid (foreign) to be dropped form analytics_train_samples.
633 $table = new xmldb_table('analytics_train_samples');
634 $key = new xmldb_key('fileid', XMLDB_KEY_FOREIGN, ['fileid'], 'files', ['id']);
635
636 // Launch drop key fileid.
637 $dbman->drop_key($table, $key);
638
639 // Define field fileid to be dropped from analytics_train_samples.
640 $table = new xmldb_table('analytics_train_samples');
641 $field = new xmldb_field('fileid');
642
643 // Conditionally launch drop field fileid.
644 if ($dbman->field_exists($table, $field)) {
645 $dbman->drop_field($table, $field);
646 }
647
648 // Main savepoint reached.
649 upgrade_main_savepoint(true, 2019040600.02);
650 }
651
29bc29ed 652 if ($oldversion < 2019040600.04) {
2cd901a4
MP
653 // Define field and index to be added to backup_controllers.
654 $table = new xmldb_table('backup_controllers');
655 $field = new xmldb_field('progress', XMLDB_TYPE_NUMBER, '15, 14', null, XMLDB_NOTNULL, null, '0', 'timemodified');
656 $index = new xmldb_index('useritem_ix', XMLDB_INDEX_NOTUNIQUE, ['userid', 'itemid']);
657 // Conditionally launch add field progress.
658 if (!$dbman->field_exists($table, $field)) {
659 $dbman->add_field($table, $field);
660 }
661 // Conditionally launch add index useritem_ix.
662 if (!$dbman->index_exists($table, $index)) {
663 $dbman->add_index($table, $index);
664 }
665
666 // Main savepoint reached.
29bc29ed 667 upgrade_main_savepoint(true, 2019040600.04);
2cd901a4
MP
668 }
669
8fa61e52 670 if ($oldversion < 2019041000.02) {
3a5afbf5 671
672 // Define field fullmessagetrust to be added to messages.
673 $table = new xmldb_table('messages');
674 $field = new xmldb_field('fullmessagetrust', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'timecreated');
675
676 // Conditionally launch add field fullmessagetrust.
677 if (!$dbman->field_exists($table, $field)) {
678 $dbman->add_field($table, $field);
679 }
680
681 // Main savepoint reached.
8fa61e52 682 upgrade_main_savepoint(true, 2019041000.02);
3a5afbf5 683 }
684
64827346
DM
685 if ($oldversion < 2019041300.01) {
686 // Add the field 'name' to the 'analytics_models' table.
687 $table = new xmldb_table('analytics_models');
688 $field = new xmldb_field('name', XMLDB_TYPE_CHAR, '1333', null, null, null, null, 'trained');
689
690 if (!$dbman->field_exists($table, $field)) {
691 $dbman->add_field($table, $field);
692 }
862a9b1d 693 // Main savepoint reached.
64827346
DM
694 upgrade_main_savepoint(true, 2019041300.01);
695 }
696
862a9b1d 697 if ($oldversion < 2019041800.01) {
734b198f
SA
698 // STEP 1. For the existing and migrated self-conversations, set the type to the new MESSAGE_CONVERSATION_TYPE_SELF, update
699 // the convhash and star them.
700 $sql = "SELECT mcm.conversationid, mcm.userid, MAX(mcm.id) as maxid
701 FROM {message_conversation_members} mcm
deef5860
SA
702 INNER JOIN {user} u ON mcm.userid = u.id
703 WHERE u.deleted = 0
734b198f
SA
704 GROUP BY mcm.conversationid, mcm.userid
705 HAVING COUNT(*) > 1";
706 $selfconversationsrs = $DB->get_recordset_sql($sql);
707 $maxids = [];
708 foreach ($selfconversationsrs as $selfconversation) {
709 $DB->update_record('message_conversations',
710 ['id' => $selfconversation->conversationid,
711 'type' => \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
712 'convhash' => \core_message\helper::get_conversation_hash([$selfconversation->userid])
713 ]
714 );
715
716 // Star the existing self-conversation.
717 $favouriterecord = new \stdClass();
718 $favouriterecord->component = 'core_message';
719 $favouriterecord->itemtype = 'message_conversations';
720 $favouriterecord->itemid = $selfconversation->conversationid;
721 $userctx = \context_user::instance($selfconversation->userid);
722 $favouriterecord->contextid = $userctx->id;
723 $favouriterecord->userid = $selfconversation->userid;
deef5860
SA
724 if (!$DB->record_exists('favourite', (array)$favouriterecord)) {
725 $favouriterecord->timecreated = time();
726 $favouriterecord->timemodified = $favouriterecord->timecreated;
727 $DB->insert_record('favourite', $favouriterecord);
728 }
734b198f
SA
729
730 // Set the self-conversation member with maxid to remove it later.
731 $maxids[] = $selfconversation->maxid;
732 }
733 $selfconversationsrs->close();
734
735 // Remove the repeated member with the higher id for all the existing self-conversations.
736 if (!empty($maxids)) {
737 list($insql, $inparams) = $DB->get_in_or_equal($maxids);
738 $DB->delete_records_select('message_conversation_members', "id $insql", $inparams);
739 }
740
741 // STEP 2. Migrate existing self-conversation relying on old message tables, setting the type to the new
742 // MESSAGE_CONVERSATION_TYPE_SELF and the convhash to the proper one. Star them also.
743
744 // On the messaging legacy tables, self-conversations are only present in the 'message_read' table, so we don't need to
745 // check the content in the 'message' table.
deef5860
SA
746 $sql = "SELECT mr.*
747 FROM {message_read} mr
748 INNER JOIN {user} u ON mr.useridfrom = u.id
749 WHERE mr.useridfrom = mr.useridto AND mr.notification = 0 AND u.deleted = 0";
750 $legacyselfmessagesrs = $DB->get_recordset_sql($sql);
734b198f
SA
751 foreach ($legacyselfmessagesrs as $message) {
752 // Get the self-conversation or create and star it if doesn't exist.
753 $conditions = [
754 'type' => \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF,
755 'convhash' => \core_message\helper::get_conversation_hash([$message->useridfrom])
756 ];
757 $selfconversation = $DB->get_record('message_conversations', $conditions);
758 if (empty($selfconversation)) {
759 // Create the self-conversation.
760 $selfconversation = new \stdClass();
761 $selfconversation->type = \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF;
762 $selfconversation->convhash = \core_message\helper::get_conversation_hash([$message->useridfrom]);
763 $selfconversation->enabled = 1;
764 $selfconversation->timecreated = time();
765 $selfconversation->timemodified = $selfconversation->timecreated;
766
767 $selfconversation->id = $DB->insert_record('message_conversations', $selfconversation);
768
769 // Add user to this self-conversation.
770 $member = new \stdClass();
771 $member->conversationid = $selfconversation->id;
772 $member->userid = $message->useridfrom;
773 $member->timecreated = time();
774
775 $member->id = $DB->insert_record('message_conversation_members', $member);
776
777 // Star the self-conversation.
778 $favouriterecord = new \stdClass();
779 $favouriterecord->component = 'core_message';
780 $favouriterecord->itemtype = 'message_conversations';
781 $favouriterecord->itemid = $selfconversation->id;
782 $userctx = \context_user::instance($message->useridfrom);
783 $favouriterecord->contextid = $userctx->id;
784 $favouriterecord->userid = $message->useridfrom;
deef5860
SA
785 if (!$DB->record_exists('favourite', (array)$favouriterecord)) {
786 $favouriterecord->timecreated = time();
787 $favouriterecord->timemodified = $favouriterecord->timecreated;
788 $DB->insert_record('favourite', $favouriterecord);
789 }
734b198f
SA
790 }
791
792 // Create the object we will be inserting into the database.
793 $tabledata = new \stdClass();
794 $tabledata->useridfrom = $message->useridfrom;
795 $tabledata->conversationid = $selfconversation->id;
796 $tabledata->subject = $message->subject;
797 $tabledata->fullmessage = $message->fullmessage;
798 $tabledata->fullmessageformat = $message->fullmessageformat ?? FORMAT_MOODLE;
799 $tabledata->fullmessagehtml = $message->fullmessagehtml;
800 $tabledata->smallmessage = $message->smallmessage;
801 $tabledata->timecreated = $message->timecreated;
802
803 $messageid = $DB->insert_record('messages', $tabledata);
804
805 // Check if we need to mark this message as deleted (self-conversations add this information on the
806 // timeuserfromdeleted field.
807 if ($message->timeuserfromdeleted) {
808 $mua = new \stdClass();
809 $mua->userid = $message->useridfrom;
810 $mua->messageid = $messageid;
811 $mua->action = \core_message\api::MESSAGE_ACTION_DELETED;
812 $mua->timecreated = $message->timeuserfromdeleted;
813
814 $DB->insert_record('message_user_actions', $mua);
815 }
816
817 // Mark this message as read.
818 $mua = new \stdClass();
819 $mua->userid = $message->useridto;
820 $mua->messageid = $messageid;
821 $mua->action = \core_message\api::MESSAGE_ACTION_READ;
822 $mua->timecreated = $message->timeread;
823
824 $DB->insert_record('message_user_actions', $mua);
50255ba9
SA
825
826 // The self-conversation message has been migrated. Delete the record from the legacy table as soon as possible
827 // to avoid migrate it twice.
828 $DB->delete_records('message_read', ['id' => $message->id]);
734b198f
SA
829 }
830 $legacyselfmessagesrs->close();
831
734b198f 832 // Main savepoint reached.
862a9b1d 833 upgrade_main_savepoint(true, 2019041800.01);
734b198f
SA
834 }
835
5dec930f 836 if ($oldversion < 2019042200.01) {
59471712
EL
837
838 // Define table role_sortorder to be dropped.
839 $table = new xmldb_table('role_sortorder');
840
841 // Conditionally launch drop table for role_sortorder.
842 if ($dbman->table_exists($table)) {
843 $dbman->drop_table($table);
844 }
845
846 // Main savepoint reached.
5dec930f 847 upgrade_main_savepoint(true, 2019042200.01);
59471712
EL
848 }
849
1f39068e 850 if ($oldversion < 2019042200.02) {
9c0edd12
EL
851
852 // Let's update all (old core) targets to their new (core_course) locations.
853 $targets = [
854 '\core\analytics\target\course_competencies' => '\core_course\analytics\target\course_competencies',
855 '\core\analytics\target\course_completion' => '\core_course\analytics\target\course_completion',
856 '\core\analytics\target\course_dropout' => '\core_course\analytics\target\course_dropout',
857 '\core\analytics\target\course_gradetopass' => '\core_course\analytics\target\course_gradetopass',
858 '\core\analytics\target\no_teaching' => '\core_course\analytics\target\no_teaching',
7063b665 859 ];
7063b665 860
9c0edd12
EL
861 foreach ($targets as $oldclass => $newclass) {
862 $DB->set_field('analytics_models', 'target', $newclass, ['target' => $oldclass]);
7063b665
DM
863 }
864
865 // Main savepoint reached.
1f39068e 866 upgrade_main_savepoint(true, 2019042200.02);
7063b665
DM
867 }
868
1470cfc2 869 if ($oldversion < 2019042300.01) {
d26749b7
SL
870 $sql = "UPDATE {capabilities}
871 SET name = ?,
872 contextlevel = ?
873 WHERE name = ?";
874 $DB->execute($sql, ['moodle/category:viewcourselist', CONTEXT_COURSECAT, 'moodle/course:browse']);
875
876 $sql = "UPDATE {role_capabilities}
877 SET capability = ?
878 WHERE capability = ?";
879 $DB->execute($sql, ['moodle/category:viewcourselist', 'moodle/course:browse']);
880
881 // Main savepoint reached.
1470cfc2 882 upgrade_main_savepoint(true, 2019042300.01);
d26749b7 883 }
1470cfc2 884
b63c0b90
DM
885 if ($oldversion < 2019042300.03) {
886
333d11c9
JL
887 // Add new customdata field to message table.
888 $table = new xmldb_table('message');
889 $field = new xmldb_field('customdata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'eventtype');
890
891 // Conditionally launch add field output.
892 if (!$dbman->field_exists($table, $field)) {
893 $dbman->add_field($table, $field);
894 }
895
896 // Add new customdata field to notifications and messages table.
897 $table = new xmldb_table('notifications');
898 $field = new xmldb_field('customdata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'timecreated');
899
900 // Conditionally launch add field output.
901 if (!$dbman->field_exists($table, $field)) {
902 $dbman->add_field($table, $field);
903 }
904
905 $table = new xmldb_table('messages');
906 // Conditionally launch add field output.
907 if (!$dbman->field_exists($table, $field)) {
908 $dbman->add_field($table, $field);
909 }
910
911 // Main savepoint reached.
b63c0b90 912 upgrade_main_savepoint(true, 2019042300.03);
333d11c9
JL
913 }
914
352ab746
DM
915 if ($oldversion < 2019042700.01) {
916
917 // Define field firstanalysis to be added to analytics_used_analysables.
918 $table = new xmldb_table('analytics_used_analysables');
919
920 // Declaring it as null initially (although it is NOT NULL).
921 $field = new xmldb_field('firstanalysis', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'analysableid');
922
923 // Conditionally launch add field firstanalysis.
924 if (!$dbman->field_exists($table, $field)) {
925 $dbman->add_field($table, $field);
926
927 // Set existing values to the current timeanalysed value.
928 $recordset = $DB->get_recordset('analytics_used_analysables');
929 foreach ($recordset as $record) {
930 $record->firstanalysis = $record->timeanalysed;
931 $DB->update_record('analytics_used_analysables', $record);
932 }
933 $recordset->close();
934
935 // Now make the field 'NOT NULL'.
936 $field = new xmldb_field('firstanalysis', XMLDB_TYPE_INTEGER, '10',
937 null, XMLDB_NOTNULL, null, null, 'analysableid');
938 $dbman->change_field_notnull($table, $field);
939 }
940
941 // Main savepoint reached.
942 upgrade_main_savepoint(true, 2019042700.01);
943 }
944
903ec849
JD
945 if ($oldversion < 2019050300.01) {
946 // Delete all stale favourite records which were left behind when a course was deleted.
903ec849 947 $params = ['component' => 'core_message', 'itemtype' => 'message_conversations'];
0eab8a42
JP
948 $sql = "SELECT fav.id as id
949 FROM {favourite} fav
950 LEFT JOIN {context} ctx ON (ctx.id = fav.contextid)
951 WHERE fav.component = :component
952 AND fav.itemtype = :itemtype
953 AND ctx.id IS NULL";
954
955 if ($records = $DB->get_fieldset_sql($sql, $params)) {
956 // Just for safety, delete by chunks.
957 $chunks = array_chunk($records, 1000);
958 foreach ($chunks as $chunk) {
959 list($insql, $inparams) = $DB->get_in_or_equal($chunk);
960 $DB->delete_records_select('favourite', "id $insql", $inparams);
961 }
962 }
903ec849
JD
963
964 upgrade_main_savepoint(true, 2019050300.01);
965 }
966
7726bec6 967 if ($oldversion < 2019050600.00) {
aae219ac
DW
968
969 // Define field apiversion to be added to badge_backpack.
970 $table = new xmldb_table('badge_backpack');
971 $field = new xmldb_field('apiversion', XMLDB_TYPE_CHAR, '12', null, XMLDB_NOTNULL, null, '1.0', 'password');
972
973 // Conditionally launch add field apiversion.
974 if (!$dbman->field_exists($table, $field)) {
975 $dbman->add_field($table, $field);
976 }
977
978 // Define table badge_external_backpack to be created.
979 $table = new xmldb_table('badge_external_backpack');
980
981 // Adding fields to table badge_external_backpack.
982 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
983 $table->add_field('backpackapiurl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
984 $table->add_field('backpackweburl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
985 $table->add_field('apiversion', XMLDB_TYPE_CHAR, '12', null, XMLDB_NOTNULL, null, '1.0');
986 $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
987 $table->add_field('password', XMLDB_TYPE_CHAR, '255', null, null, null, null);
988
989 // Adding keys to table badge_external_backpack.
990 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
991 $table->add_key('backpackapiurlkey', XMLDB_KEY_UNIQUE, ['backpackapiurl']);
992 $table->add_key('backpackweburlkey', XMLDB_KEY_UNIQUE, ['backpackweburl']);
993
994 // Conditionally launch create table for badge_external_backpack.
995 if (!$dbman->table_exists($table)) {
996 $dbman->create_table($table);
997 }
998
999 // Define field entityid to be added to badge_external.
1000 $table = new xmldb_table('badge_external');
1001 $field = new xmldb_field('entityid', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'collectionid');
1002
1003 // Conditionally launch add field entityid.
1004 if (!$dbman->field_exists($table, $field)) {
1005 $dbman->add_field($table, $field);
1006 }
1007
7444ba74 1008 // Define table badge_external_identifier to be created.
aae219ac
DW
1009 $table = new xmldb_table('badge_external_identifier');
1010
1011 // Adding fields to table badge_external_identifier.
1012 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1013 $table->add_field('sitebackpackid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1014 $table->add_field('internalid', XMLDB_TYPE_CHAR, '128', null, XMLDB_NOTNULL, null, null);
1015 $table->add_field('externalid', XMLDB_TYPE_CHAR, '128', null, XMLDB_NOTNULL, null, null);
1016 $table->add_field('type', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, null);
1017
1018 // Adding keys to table badge_external_identifier.
1019 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1020 $table->add_key('fk_backpackid', XMLDB_KEY_FOREIGN, ['sitebackpackid'], 'badge_backpack', ['id']);
1021 $table->add_key('backpack-internal-external', XMLDB_KEY_UNIQUE, ['sitebackpackid', 'internalid', 'externalid', 'type']);
1022
1023 // Conditionally launch create table for badge_external_identifier.
1024 if (!$dbman->table_exists($table)) {
1025 $dbman->create_table($table);
1026 }
7444ba74
DW
1027
1028 // Define field externalbackpackid to be added to badge_backpack.
1029 $table = new xmldb_table('badge_backpack');
1030 $field = new xmldb_field('externalbackpackid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'password');
1031
1032 // Conditionally launch add field externalbackpackid.
1033 if (!$dbman->field_exists($table, $field)) {
1034 $dbman->add_field($table, $field);
1035 }
1036
1037 // Define key externalbackpack (foreign) to be added to badge_backpack.
1038 $key = new xmldb_key('externalbackpack', XMLDB_KEY_FOREIGN, ['externalbackpackid'], 'badge_external_backpack', ['id']);
1039
1040 // Launch add key externalbackpack.
1041 $dbman->add_key($table, $key);
1042
1043 $field = new xmldb_field('apiversion');
1044
1045 // Conditionally launch drop field apiversion.
1046 if ($dbman->field_exists($table, $field)) {
1047 $dbman->drop_field($table, $field);
1048 }
1049
1050 $field = new xmldb_field('backpackurl');
1051
1052 // Conditionally launch drop field backpackurl.
1053 if ($dbman->field_exists($table, $field)) {
1054 $dbman->drop_field($table, $field);
1055 }
1056
1057 // Add default backpacks.
9ad5cff4 1058 require_once($CFG->dirroot . '/badges/upgradelib.php'); // Core install and upgrade related functions only for badges.
7444ba74
DW
1059 badges_install_default_backpacks();
1060
aae219ac 1061 // Main savepoint reached.
7726bec6 1062 upgrade_main_savepoint(true, 2019050600.00);
aae219ac
DW
1063 }
1064
d9b6bd95 1065 if ($oldversion < 2019051300.01) {
bc2f679b
DM
1066 $DB->set_field('analytics_models', 'enabled', '1', ['target' => '\core_user\analytics\target\upcoming_activities_due']);
1067
1068 // Main savepoint reached.
d9b6bd95 1069 upgrade_main_savepoint(true, 2019051300.01);
bc2f679b
DM
1070 }
1071
3572a25c
EL
1072 // Automatically generated Moodle v3.7.0 release upgrade line.
1073 // Put any upgrade step following this.
1074
76d0192e
MH
1075 if ($oldversion < 2019060600.02) {
1076 // Renaming 'opentogoogle' config to 'opentowebcrawlers'.
1077 $opentogooglevalue = get_config('core', 'opentogoogle');
1078
1079 // Move the value over if it was previously configured.
1080 if ($opentogooglevalue !== false) {
1081 set_config('opentowebcrawlers', $opentogooglevalue);
1082 }
1083
1084 // Remove the now unused value.
1085 unset_config('opentogoogle');
1086
1087 // Main savepoint reached.
1088 upgrade_main_savepoint(true, 2019060600.02);
1089 }
1090
22dfa6d3
DM
1091 if ($oldversion < 2019062900.00) {
1092 // Debugsmtp is now only available via config.php.
1093 $DB->delete_records('config', array('name' => 'debugsmtp'));
1094
1095 // Main savepoint reached.
1096 upgrade_main_savepoint(true, 2019062900.00);
1097 }
1098
c5b2ab47
BB
1099 if ($oldversion < 2019070400.01) {
1100
1101 $basecolors = ['#81ecec', '#74b9ff', '#a29bfe', '#dfe6e9', '#00b894',
1102 '#0984e3', '#b2bec3', '#fdcb6e', '#fd79a8', '#6c5ce7'];
1103
1104 $colornr = 1;
1105 foreach ($basecolors as $color) {
1106 set_config('coursecolor' . $colornr, $color, 'core_admin');
1107 $colornr++;
1108 }
1109
1110 upgrade_main_savepoint(true, 2019070400.01);
1111 }
1112
9d8cdb9b
JP
1113 if ($oldversion < 2019072200.00) {
1114
1115 // Define field relativedatesmode to be added to course.
1116 $table = new xmldb_table('course');
1117 $field = new xmldb_field('relativedatesmode', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'enddate');
1118
1119 // Conditionally launch add field relativedatesmode.
1120 if (!$dbman->field_exists($table, $field)) {
1121 $dbman->add_field($table, $field);
1122 }
1123
1124 // Main savepoint reached.
1125 upgrade_main_savepoint(true, 2019072200.00);
1126 }
1127
1f16f411 1128 if ($oldversion < 2019072500.01) {
5d61b3b3
RW
1129 // Remove the "popup" processor from the list of default processors for the messagecontactrequests notification.
1130 $oldloggedinconfig = get_config('message', 'message_provider_moodle_messagecontactrequests_loggedin');
1131 $oldloggedoffconfig = get_config('message', 'message_provider_moodle_messagecontactrequests_loggedoff');
1132 $newloggedinconfig = implode(',', array_filter(explode(',', $oldloggedinconfig), function($value) {
1133 return $value != 'popup';
1134 }));
1135 $newloggedoffconfig = implode(',', array_filter(explode(',', $oldloggedoffconfig), function($value) {
1136 return $value != 'popup';
1137 }));
1138 set_config('message_provider_moodle_messagecontactrequests_loggedin', $newloggedinconfig, 'message');
1139 set_config('message_provider_moodle_messagecontactrequests_loggedoff', $newloggedoffconfig, 'message');
1140
1f16f411 1141 upgrade_main_savepoint(true, 2019072500.01);
5d61b3b3
RW
1142 }
1143
a12f9f93
JD
1144 if ($oldversion < 2019072500.03) {
1145 unset_config('httpswwwroot');
1146
1147 upgrade_main_savepoint(true, 2019072500.03);
1148 }
1149
d8b3c365 1150 if ($oldversion < 2019073100.00) {
0c187454
MM
1151 // Update the empty tag instructions to null.
1152 $instructions = get_config('core', 'auth_instructions');
1153
1154 if (trim(html_to_text($instructions)) === '') {
1155 set_config('auth_instructions', '');
1156 }
1157
1158 // Main savepoint reached.
d8b3c365 1159 upgrade_main_savepoint(true, 2019073100.00);
0c187454 1160 }
1d6f041a 1161
3213963f 1162 if ($oldversion < 2019083000.01) {
1d6f041a
P
1163
1164 // If block_community is no longer present, remove it.
1165 if (!file_exists($CFG->dirroot . '/blocks/community/communitycourse.php')) {
1166 // Drop table that is no longer needed.
1167 $table = new xmldb_table('block_community');
1168 if ($dbman->table_exists($table)) {
1169 $dbman->drop_table($table);
1170 }
1171
1172 // Delete instances.
1173 $instances = $DB->get_records_list('block_instances', 'blockname', ['community']);
1174 $instanceids = array_keys($instances);
1175
1176 if (!empty($instanceids)) {
1177 $DB->delete_records_list('block_positions', 'blockinstanceid', $instanceids);
1178 $DB->delete_records_list('block_instances', 'id', $instanceids);
1179 list($sql, $params) = $DB->get_in_or_equal($instanceids, SQL_PARAMS_NAMED);
1180 $params['contextlevel'] = CONTEXT_BLOCK;
1181 $DB->delete_records_select('context', "contextlevel=:contextlevel AND instanceid " . $sql, $params);
1182
1183 $preferences = array();
1184 foreach ($instances as $instanceid => $instance) {
1185 $preferences[] = 'block' . $instanceid . 'hidden';
1186 $preferences[] = 'docked_block_instance_' . $instanceid;
1187 }
1188 $DB->delete_records_list('user_preferences', 'name', $preferences);
1189 }
1190
1191 // Delete the block from the block table.
1192 $DB->delete_records('block', array('name' => 'community'));
1193
1194 // Remove capabilities.
1195 capabilities_cleanup('block_community');
1196 // Clean config.
1197 unset_all_config_for_plugin('block_community');
1198
1199 // Remove Moodle-level community based capabilities.
1200 $capabilitiestoberemoved = ['block/community:addinstance', 'block/community:myaddinstance'];
1201 // Delete any role_capabilities for the old roles.
1202 $DB->delete_records_list('role_capabilities', 'capability', $capabilitiestoberemoved);
1203 // Delete the capability itself.
1204 $DB->delete_records_list('capabilities', 'name', $capabilitiestoberemoved);
1205 }
1206
3213963f 1207 upgrade_main_savepoint(true, 2019083000.01);
1d6f041a
P
1208 }
1209
020bad73
P
1210 if ($oldversion < 2019083000.02) {
1211 // Remove unused config.
1212 unset_config('enablecoursepublishing');
1213 upgrade_main_savepoint(true, 2019083000.02);
1214 }
1215
cd1bdc79 1216 if ($oldversion < 2019083000.04) {
8c07d7d7
SL
1217 // Delete "orphaned" subscriptions.
1218 $sql = "SELECT DISTINCT es.userid
1219 FROM {event_subscriptions} es
1220 LEFT JOIN {user} u ON u.id = es.userid
1221 WHERE u.deleted = 1 OR u.id IS NULL";
3364e18b 1222 $deletedusers = $DB->get_fieldset_sql($sql);
8c07d7d7
SL
1223 if ($deletedusers) {
1224 list($sql, $params) = $DB->get_in_or_equal($deletedusers);
1225
1226 // Delete orphaned subscriptions.
1227 $DB->execute("DELETE FROM {event_subscriptions} WHERE userid " . $sql, $params);
1228 }
1229
cd1bdc79 1230 upgrade_main_savepoint(true, 2019083000.04);
8c07d7d7
SL
1231 }
1232
f5583e97
DM
1233 if ($oldversion < 2019090500.01) {
1234
1235 // Define index analysableid (not unique) to be added to analytics_used_analysables.
1236 $table = new xmldb_table('analytics_used_analysables');
1237 $index = new xmldb_index('analysableid', XMLDB_INDEX_NOTUNIQUE, ['analysableid']);
1238
1239 // Conditionally launch add index analysableid.
1240 if (!$dbman->index_exists($table, $index)) {
1241 $dbman->add_index($table, $index);
1242 }
1243
1244 // Main savepoint reached.
1245 upgrade_main_savepoint(true, 2019090500.01);
1246 }
1247
386d1091
DM
1248 if ($oldversion < 2019092700.01) {
1249 upgrade_rename_prediction_actions_useful_incorrectly_flagged();
1250 upgrade_main_savepoint(true, 2019092700.01);
1251 }
1252
13ef95e3 1253 if ($oldversion < 2019100800.02) {
ecc9960e
DM
1254 // Rename the official moodle sites directory the site is registered with.
1255 $DB->execute("UPDATE {registration_hubs}
1256 SET hubname = ?, huburl = ?
1257 WHERE huburl = ?", ['moodle', 'https://stats.moodle.org', 'https://moodle.net']);
1258
1259 // Convert the hub site specific settings to the new naming format without the hub URL in the name.
1260 $hubconfig = get_config('hub');
1261
1262 if (!empty($hubconfig)) {
1263 foreach (upgrade_convert_hub_config_site_param_names($hubconfig, 'https://moodle.net') as $name => $value) {
1264 set_config($name, $value, 'hub');
1265 }
1266 }
1267
13ef95e3 1268 upgrade_main_savepoint(true, 2019100800.02);
ecc9960e
DM
1269 }
1270
d31b5c43 1271 if ($oldversion < 2019100900.00) {
7ce941a4
AB
1272 // If block_participants is no longer present, remove it.
1273 if (!file_exists($CFG->dirroot . '/blocks/participants/block_participants.php')) {
1274 // Delete instances.
1275 $instances = $DB->get_records_list('block_instances', 'blockname', ['participants']);
1276 $instanceids = array_keys($instances);
1277
1278 if (!empty($instanceids)) {
1279 $DB->delete_records_list('block_positions', 'blockinstanceid', $instanceids);
1280 $DB->delete_records_list('block_instances', 'id', $instanceids);
1281 list($sql, $params) = $DB->get_in_or_equal($instanceids, SQL_PARAMS_NAMED);
1282 $params['contextlevel'] = CONTEXT_BLOCK;
1283 $DB->delete_records_select('context', "contextlevel=:contextlevel AND instanceid " . $sql, $params);
1284
1285 $preferences = array();
1286 foreach ($instances as $instanceid => $instance) {
1287 $preferences[] = 'block' . $instanceid . 'hidden';
1288 $preferences[] = 'docked_block_instance_' . $instanceid;
1289 }
1290 $DB->delete_records_list('user_preferences', 'name', $preferences);
1291 }
1292
1293 // Delete the block from the block table.
1294 $DB->delete_records('block', array('name' => 'participants'));
1295
1296 // Remove capabilities.
1297 capabilities_cleanup('block_participants');
1298
1299 // Clean config.
1300 unset_all_config_for_plugin('block_participants');
1301 }
1302
d31b5c43 1303 upgrade_main_savepoint(true, 2019100900.00);
7ce941a4
AB
1304 }
1305
6d98de3f 1306 if ($oldversion < 2019101600.01) {
959e4f0e
MG
1307
1308 // Change the setting $CFG->requestcategoryselection into $CFG->lockrequestcategory with opposite value.
25676441 1309 set_config('lockrequestcategory', empty($CFG->requestcategoryselection));
959e4f0e 1310
6d98de3f 1311 upgrade_main_savepoint(true, 2019101600.01);
959e4f0e
MG
1312 }
1313
7ba9c635 1314 if ($oldversion < 2019101800.02) {
c345aa72
MM
1315
1316 // Get the table by its previous name.
1317 $table = new xmldb_table('analytics_models');
1318 if ($dbman->table_exists($table)) {
1319
1320 // Define field contextids to be added to analytics_models.
1321 $field = new xmldb_field('contextids', XMLDB_TYPE_TEXT, null, null, null, null, null, 'version');
1322
1323 // Conditionally launch add field contextids.
1324 if (!$dbman->field_exists($table, $field)) {
1325 $dbman->add_field($table, $field);
1326 }
1327 }
1328
1329 // Main savepoint reached.
7ba9c635 1330 upgrade_main_savepoint(true, 2019101800.02);
c345aa72
MM
1331 }
1332
6850374b 1333 if ($oldversion < 2019102500.04) {
bb4f59f8
AA
1334 // Define table h5p_libraries to be created.
1335 $table = new xmldb_table('h5p_libraries');
1336
1337 // Adding fields to table h5p_libraries.
1338 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1339 $table->add_field('machinename', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1340 $table->add_field('title', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1341 $table->add_field('majorversion', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null);
1342 $table->add_field('minorversion', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null);
1343 $table->add_field('patchversion', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null);
1344 $table->add_field('runnable', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null);
1345 $table->add_field('fullscreen', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
1346 $table->add_field('embedtypes', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1347 $table->add_field('preloadedjs', XMLDB_TYPE_TEXT, null, null, null, null, null);
1348 $table->add_field('preloadedcss', XMLDB_TYPE_TEXT, null, null, null, null, null);
1349 $table->add_field('droplibrarycss', XMLDB_TYPE_TEXT, null, null, null, null, null);
1350 $table->add_field('semantics', XMLDB_TYPE_TEXT, null, null, null, null, null);
1351 $table->add_field('addto', XMLDB_TYPE_TEXT, null, null, null, null, null);
1352
1353 // Adding keys to table h5p_libraries.
1354 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1355
1356 // Adding indexes to table h5p_libraries.
1357 $table->add_index('machinemajorminorpatch', XMLDB_INDEX_NOTUNIQUE,
1358 ['machinename', 'majorversion', 'minorversion', 'patchversion', 'runnable']);
1359
1360 // Conditionally launch create table for h5p_libraries.
1361 if (!$dbman->table_exists($table)) {
1362 $dbman->create_table($table);
1363 }
1364
1365 // Define table h5p_library_dependencies to be created.
1366 $table = new xmldb_table('h5p_library_dependencies');
1367
1368 // Adding fields to table h5p_library_dependencies.
1369 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1370 $table->add_field('libraryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1371 $table->add_field('requiredlibraryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1372 $table->add_field('dependencytype', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1373
1374 // Adding keys to table h5p_library_dependencies.
1375 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1376 $table->add_key('libraryid', XMLDB_KEY_FOREIGN, ['libraryid'], 'h5p_libraries', ['id']);
1377 $table->add_key('requiredlibraryid', XMLDB_KEY_FOREIGN, ['requiredlibraryid'], 'h5p_libraries', ['id']);
1378
1379 // Conditionally launch create table for h5p_library_dependencies.
1380 if (!$dbman->table_exists($table)) {
1381 $dbman->create_table($table);
1382 }
1383
1384 // Define table h5p to be created.
1385 $table = new xmldb_table('h5p');
1386
1387 // Adding fields to table h5p.
1388 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1389 $table->add_field('jsoncontent', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
1390 $table->add_field('mainlibraryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1391 $table->add_field('displayoptions', XMLDB_TYPE_INTEGER, '4', null, null, null, null);
1392 $table->add_field('pathnamehash', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null);
1393 $table->add_field('contenthash', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null);
1394 $table->add_field('filtered', XMLDB_TYPE_TEXT, null, null, null, null, null);
1395 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1396 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1397
1398 // Adding keys to table h5p.
1399 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1400 $table->add_key('mainlibraryid', XMLDB_KEY_FOREIGN, ['mainlibraryid'], 'h5p_libraries', ['id']);
1401
1402 // Conditionally launch create table for h5p.
1403 if (!$dbman->table_exists($table)) {
1404 $dbman->create_table($table);
1405 }
1406
1407 // Define table h5p_contents_libraries to be created.
1408 $table = new xmldb_table('h5p_contents_libraries');
1409
1410 // Adding fields to table h5p_contents_libraries.
1411 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1412 $table->add_field('h5pid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1413 $table->add_field('libraryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1414 $table->add_field('dependencytype', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, null);
1415 $table->add_field('dropcss', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null);
1416 $table->add_field('weight', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1417
1418 // Adding keys to table h5p_contents_libraries.
1419 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1420 $table->add_key('h5pid', XMLDB_KEY_FOREIGN, ['h5pid'], 'h5p', ['id']);
1421 $table->add_key('libraryid', XMLDB_KEY_FOREIGN, ['libraryid'], 'h5p_libraries', ['id']);
1422
1423 // Conditionally launch create table for h5p_contents_libraries.
1424 if (!$dbman->table_exists($table)) {
1425 $dbman->create_table($table);
1426 }
1427
1428 // Define table h5p_libraries_cachedassets to be created.
1429 $table = new xmldb_table('h5p_libraries_cachedassets');
1430
1431 // Adding fields to table h5p_libraries_cachedassets.
1432 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1433 $table->add_field('libraryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1434 $table->add_field('hash', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1435
1436 // Adding keys to table h5p_libraries_cachedassets.
1437 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1438 $table->add_key('libraryid', XMLDB_KEY_FOREIGN, ['libraryid'], 'h5p_libraries_cachedassets', ['id']);
1439
1440 // Conditionally launch create table for h5p_libraries_cachedassets.
1441 if (!$dbman->table_exists($table)) {
1442 $dbman->create_table($table);
1443 }
1444
1445 // Main savepoint reached.
6850374b 1446 upgrade_main_savepoint(true, 2019102500.04);
bb4f59f8
AA
1447 }
1448
ef05f292
DM
1449 if ($oldversion < 2019103000.13) {
1450
a461d360 1451 upgrade_analytics_fix_contextids_defaults();
ef05f292
DM
1452
1453 // Main savepoint reached.
1454 upgrade_main_savepoint(true, 2019103000.13);
1455 }
1456
09ab0027 1457 if ($oldversion < 2019111300.00) {
b7c307f3
VDF
1458
1459 // Define field coremajor to be added to h5p_libraries.
1460 $table = new xmldb_table('h5p_libraries');
1461 $field = new xmldb_field('coremajor', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'addto');
1462
1463 // Conditionally launch add field coremajor.
1464 if (!$dbman->field_exists($table, $field)) {
1465 $dbman->add_field($table, $field);
1466 }
1467
1468 $field = new xmldb_field('coreminor', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'coremajor');
1469
1470 // Conditionally launch add field coreminor.
1471 if (!$dbman->field_exists($table, $field)) {
1472 $dbman->add_field($table, $field);
1473 }
1474
1475 // Main savepoint reached.
09ab0027 1476 upgrade_main_savepoint(true, 2019111300.00);
b7c307f3
VDF
1477 }
1478
492d047d
EL
1479 // Automatically generated Moodle v3.8.0 release upgrade line.
1480 // Put any upgrade step following this.
1481
ae0263de 1482 if ($oldversion < 2019120500.01) {
ae0263de
JD
1483 // Delete any role assignments for roles which no longer exist.
1484 $DB->delete_records_select('role_assignments', "roleid NOT IN (SELECT id FROM {role})");
1485
1486 // Main savepoint reached.
1487 upgrade_main_savepoint(true, 2019120500.01);
1488 }
1489
a9e4fa8e 1490 if ($oldversion < 2019121800.00) {
bdf62bba
MP
1491 // Upgrade MIME types for existing streaming files.
1492 $filetypes = array(
1493 '%.fmp4' => 'video/mp4',
1494 '%.ts' => 'video/MP2T',
1495 '%.mpd' => 'application/dash+xml',
1496 '%.m3u8' => 'application/x-mpegURL',
1497 );
1498
1499 $select = $DB->sql_like('filename', '?', false);
1500 foreach ($filetypes as $extension => $mimetype) {
1501 $DB->set_field_select(
1502 'files',
1503 'mimetype',
1504 $mimetype,
1505 $select,
1506 array($extension)
1507 );
1508 }
1509
a9e4fa8e 1510 upgrade_main_savepoint(true, 2019121800.00);
bdf62bba
MP
1511 }
1512
f0d3d502
SA
1513 if ($oldversion < 2019122000.01) {
1514 // Clean old upgrade setting not used anymore.
1515 unset_config('linkcoursesectionsupgradescriptwasrun');
1516 upgrade_main_savepoint(true, 2019122000.01);
1517 }
1518
2fc2dfbb
NM
1519 if ($oldversion < 2020010900.02) {
1520 $table = new xmldb_table('event');
1521
1522 // This index will improve the performance when the Events API retrieves category and group events.
1523 $index = new xmldb_index('eventtype', XMLDB_INDEX_NOTUNIQUE, ['eventtype']);
1524 if (!$dbman->index_exists($table, $index)) {
1525 $dbman->add_index($table, $index);
1526 }
1527
1528 // This index improves the performance of backups, deletion and visibilty changes on activities.
1529 $index = new xmldb_index('modulename-instance', XMLDB_INDEX_NOTUNIQUE, ['modulename', 'instance']);
1530 if (!$dbman->index_exists($table, $index)) {
1531 $dbman->add_index($table, $index);
1532 }
1533
1534 upgrade_main_savepoint(true, 2020010900.02);
1535 }
f35e360a
SL
1536
1537 if ($oldversion < 2020011700.02) {
1538 // Delete all orphaned subscription events.
1539 $select = "subscriptionid IS NOT NULL
1540 AND subscriptionid NOT IN (SELECT id from {event_subscriptions})";
1541 $DB->delete_records_select('event', $select);
1542
1543 upgrade_main_savepoint(true, 2020011700.02);
1544 }
1545
507c3482
SL
1546 if ($oldversion < 2020013000.01) {
1547 global $DB;
1548 // Delete any associated files.
1549 $fs = get_file_storage();
1550 $sql = "SELECT cuc.id, cuc.userid
1551 FROM {competency_usercomp} cuc
1552 LEFT JOIN {user} u ON cuc.userid = u.id
1553 WHERE u.deleted = 1";
1554 $usercompetencies = $DB->get_records_sql($sql);
1555 foreach ($usercompetencies as $usercomp) {
1556 $DB->delete_records('competency_evidence', ['usercompetencyid' => $usercomp->id]);
1557 $DB->delete_records('competency_usercompcourse', ['userid' => $usercomp->userid]);
1558 $DB->delete_records('competency_usercompplan', ['userid' => $usercomp->userid]);
1559 $DB->delete_records('competency_usercomp', ['userid' => $usercomp->userid]);
1560 }
1561
1562 $sql = "SELECT cue.id, cue.userid
1563 FROM {competency_userevidence} cue
1564 LEFT JOIN {user} u ON cue.userid = u.id
1565 WHERE u.deleted = 1";
1566 $userevidences = $DB->get_records_sql($sql);
1567 foreach ($userevidences as $userevidence) {
1568 $DB->delete_records('competency_userevidencecomp', ['userevidenceid' => $userevidence->id]);
1569 $DB->delete_records('competency_userevidence', ['id' => $userevidence->id]);
1570
629ea1f9
SL
1571 if ($record = $DB->get_record('context', ['contextlevel' => CONTEXT_USER, 'instanceid' => $userevidence->userid],
1572 '*', IGNORE_MISSING)) {
1573 // Delete all orphaned user evidences files.
1574 $fs->delete_area_files($record->id, 'core_competency', 'userevidence', $userevidence->userid);
1575 }
507c3482
SL
1576 }
1577
1578 $sql = "SELECT cp.id
1579 FROM {competency_plan} cp
1580 LEFT JOIN {user} u ON cp.userid = u.id
1581 WHERE u.deleted = 1";
1582 $userplans = $DB->get_records_sql($sql);
1583 foreach ($userplans as $userplan) {
1584 $DB->delete_records('competency_plancomp', ['planid' => $userplan->id]);
1585 $DB->delete_records('competency_plan', ['id' => $userplan->id]);
1586 }
1587
1588 // Main savepoint reached.
1589 upgrade_main_savepoint(true, 2020013000.01);
1590 }
1591
abde761c
PH
1592 if ($oldversion < 2020040200.01) {
1593 // Clean up completion criteria records referring to courses that no longer exist.
1594 $select = 'criteriatype = :type AND courseinstance NOT IN (SELECT id FROM {course})';
1595 $params = ['type' => 8]; // COMPLETION_CRITERIA_TYPE_COURSE.
1596
1597 $DB->delete_records_select('course_completion_criteria', $select, $params);
1598
1599 // Main savepoint reached.
1600 upgrade_main_savepoint(true, 2020040200.01);
1601 }
1602
f1f1497f 1603 if ($oldversion < 2020040700.00) {
f958f5c1
SA
1604 // Remove deprecated Mozilla OpenBadges backpack.
1605 $url = 'https://backpack.openbadges.org';
1606 $bp = $DB->get_record('badge_external_backpack', ['backpackapiurl' => $url]);
1607 if ($bp) {
1608 // Remove connections for users to this backpack.
1609 $sql = "SELECT DISTINCT bb.id
1610 FROM {badge_backpack} bb
1611 LEFT JOIN {badge_external} be ON be. backpackid = bb.externalbackpackid
1612 WHERE bb.externalbackpackid = :backpackid";
1613 $params = ['backpackid' => $bp->id];
1614 $externalbackpacks = $DB->get_fieldset_sql($sql, $params);
1615 if ($externalbackpacks) {
1616 list($sql, $params) = $DB->get_in_or_equal($externalbackpacks);
1617
1618 // Delete user external collections references to this backpack.
1619 $DB->execute("DELETE FROM {badge_external} WHERE backpackid " . $sql, $params);
1620 }
1621 $DB->delete_records('badge_backpack', ['externalbackpackid' => $bp->id]);
1622
1623 // Delete deprecated backpack entry.
1624 $DB->delete_records('badge_external_backpack', ['backpackapiurl' => $url]);
1625 }
1626
1627 // Set active external backpack to Badgr.io.
1628 $url = 'https://api.badgr.io/v2';
1629 if ($bp = $DB->get_record('badge_external_backpack', ['backpackapiurl' => $url])) {
1630 set_config('badges_site_backpack', $bp->id);
1631 } else {
1632 unset_config('badges_site_backpack');
1633 }
1634
f1f1497f 1635 upgrade_main_savepoint(true, 2020040700.00);
f958f5c1
SA
1636 }
1637
33b8ca26
AA
1638 if ($oldversion < 2020041500.00) {
1639 // Define table to store contentbank contents.
1640 $table = new xmldb_table('contentbank_content');
1641
1642 // Adding fields to table content_bank.
1643 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1644 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1645 $table->add_field('contenttype', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
1646 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1647 $table->add_field('instanceid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1648 $table->add_field('configdata', XMLDB_TYPE_TEXT, null, null, null, null, null);
1649 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1650 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1651 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1652 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, '0');
1653
1654 // Adding keys to table contentbank_content.
1655 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1656 $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']);
1657 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']);
1658 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']);
1659
1660 // Adding indexes to table contentbank_content.
1661 $table->add_index('name', XMLDB_INDEX_NOTUNIQUE, ['name']);
1662 $table->add_index('instance', XMLDB_INDEX_NOTUNIQUE, ['contextid', 'contenttype', 'instanceid']);
1663
1664 if (!$dbman->table_exists($table)) {
1665 $dbman->create_table($table);
1666 }
1667
1668 // Main savepoint reached.
1669 upgrade_main_savepoint(true, 2020041500.00);
1670 }
3f5e386d 1671
1672 if ($oldversion < 2020041700.01) {
1673 // Upgrade h5p MIME type for existing h5p files.
1674 $select = $DB->sql_like('filename', '?', false);
1675 $DB->set_field_select(
1676 'files',
1677 'mimetype',
1678 'application/zip.h5p',
1679 $select,
1680 array('%.h5p')
1681 );
1682
1683 upgrade_main_savepoint(true, 2020041700.01);
1684 }
1685
78adf6f6
DM
1686 if ($oldversion < 2020042800.01) {
1687 // Delete obsolete config value.
1688 unset_config('enablesafebrowserintegration');
1689 // Clean up config of the old plugin.
1690 unset_all_config_for_plugin('quizaccess_safebrowser');
1691
1692 upgrade_main_savepoint(true, 2020042800.01);
1693 }
1a972b06
MG
1694
1695 if ($oldversion < 2020051900.01) {
1696 // Define field component to be added to event.
1697 $table = new xmldb_table('event');
1698 $field = new xmldb_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'repeatid');
1699
1700 // Conditionally launch add field component.
1701 if (!$dbman->field_exists($table, $field)) {
1702 $dbman->add_field($table, $field);
1703 }
1704
1705 // Define index component (not unique) to be added to event.
1706 $table = new xmldb_table('event');
1707 $index = new xmldb_index('component', XMLDB_INDEX_NOTUNIQUE, ['component', 'eventtype', 'instance']);
1708
1709 // Conditionally launch add index component.
1710 if (!$dbman->index_exists($table, $index)) {
1711 $dbman->add_index($table, $index);
1712 }
1713
1714 // Main savepoint reached.
1715 upgrade_main_savepoint(true, 2020051900.01);
1716 }
1717
7ce7d215 1718 if ($oldversion < 2020052000.00) {
15a00bea
TT
1719 // Define table badge_backpack_oauth2 to be created.
1720 $table = new xmldb_table('badge_backpack_oauth2');
1721
1722 // Adding fields to table badge_backpack_oauth2.
1723 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1724 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1725 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1726 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1727 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1728 $table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1729 $table->add_field('externalbackpackid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1730 $table->add_field('token', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
1731 $table->add_field('refreshtoken', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
1732 $table->add_field('expires', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1733 $table->add_field('scope', XMLDB_TYPE_TEXT, null, null, null, null, null);
1734
1735 // Adding keys to table badge_backpack_oauth2.
1736 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1737 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']);
1738 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
1739 $table->add_key('issuerid', XMLDB_KEY_FOREIGN, ['issuerid'], 'oauth2_issuer', ['id']);
1740 $table->add_key('externalbackpackid', XMLDB_KEY_FOREIGN, ['externalbackpackid'], 'badge_external_backpack', ['id']);
1741 // Conditionally launch create table for badge_backpack_oauth2.
1742 if (!$dbman->table_exists($table)) {
1743 $dbman->create_table($table);
1744 }
1745
1746 // Define field oauth2_issuerid to be added to badge_external_backpack.
1747 $tablebadgeexternalbackpack = new xmldb_table('badge_external_backpack');
1748 $fieldoauth2issuerid = new xmldb_field('oauth2_issuerid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'password');
1749 $keybackpackoauth2key = new xmldb_key('backpackoauth2key', XMLDB_KEY_FOREIGN, ['oauth2_issuerid'], 'oauth2_issuer', ['id']);
1750
1751 // Conditionally launch add field oauth2_issuerid.
1752 if (!$dbman->field_exists($tablebadgeexternalbackpack, $fieldoauth2issuerid)) {
1753 $dbman->add_field($tablebadgeexternalbackpack, $fieldoauth2issuerid);
1754
1755 // Launch add key backpackoauth2key.
1756 $dbman->add_key($tablebadgeexternalbackpack, $keybackpackoauth2key);
1757 }
1758
1759 // Define field assertion to be added to badge_external.
1760 $tablebadgeexternal = new xmldb_table('badge_external');
1761 $fieldassertion = new xmldb_field('assertion', XMLDB_TYPE_TEXT, null, null, null, null, null, 'entityid');
1762
1763 // Conditionally launch add field assertion.
1764 if (!$dbman->field_exists($tablebadgeexternal, $fieldassertion)) {
1765 $dbman->add_field($tablebadgeexternal, $fieldassertion);
1766 }
1767
1768 // Main savepoint reached.
7ce7d215 1769 upgrade_main_savepoint(true, 2020052000.00);
15a00bea
TT
1770 }
1771
4399e475
TD
1772 if ($oldversion < 2020052200.01) {
1773
1774 // Define field custom to be added to license.
1775 $table = new xmldb_table('license');
1776 $field = new xmldb_field('custom', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
1777
1778 // Conditionally launch add field custom.
1779 if (!$dbman->field_exists($table, $field)) {
1780 $dbman->add_field($table, $field);
1781 }
1782
1783 // Define field sortorder to be added to license.
1784 $field = new xmldb_field('sortorder', XMLDB_TYPE_INTEGER, '5', null, XMLDB_NOTNULL, null, '0');
1785
1786 // Conditionally launch add field sortorder.
1787 if (!$dbman->field_exists($table, $field)) {
1788 $dbman->add_field($table, $field);
1789 }
1790
1791 // Define index license (not unique) to be added to files.
1792 $table = new xmldb_table('files');
1793 $index = new xmldb_index('license', XMLDB_INDEX_NOTUNIQUE, ['license']);
1794
1795 // Conditionally launch add index license.
1796 if (!$dbman->index_exists($table, $index)) {
1797 $dbman->add_index($table, $index);
1798 }
1799
1800 // Upgrade the core license details.
1801 upgrade_core_licenses();
1802
1803 // Main savepoint reached.
1804 upgrade_main_savepoint(true, 2020052200.01);
1805 }
1806
16d77f18
MM
1807 if ($oldversion < 2020060500.01) {
1808 // Define field moodlenetprofile to be added to user.
1809 $table = new xmldb_table('user');
1810 $field = new xmldb_field('moodlenetprofile', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'alternatename');
1811
1812 // Conditionally launch add field moodlenetprofile.
1813 if (!$dbman->field_exists($table, $field)) {
1814 $dbman->add_field($table, $field);
1815 }
1816
1817 // Main savepoint reached.
1818 upgrade_main_savepoint(true, 2020060500.01);
1819 }
1820
b764343e
EL
1821 // Automatically generated Moodle v3.9.0 release upgrade line.
1822 // Put any upgrade step following this.
57a005e7
NM
1823 if ($oldversion < 2020061500.02) {
1824 // Update default digital age consent map according to the current legislation on each country.
1825
1826 // The default age of digital consent map for 38 and below.
1827 $oldageofdigitalconsentmap = implode(PHP_EOL, [
1828 '*, 16',
1829 'AT, 14',
1830 'ES, 14',
1831 'US, 13'
1832 ]);
1833
1834 // Check if the current age of digital consent map matches the old one.
1835 if (get_config('moodle', 'agedigitalconsentmap') === $oldageofdigitalconsentmap) {
1836 // If the site is still using the old defaults, upgrade to the new default.
1837 $ageofdigitalconsentmap = implode(PHP_EOL, [
1838 '*, 16',
1839 'AT, 14',
1840 'BE, 13',
1841 'BG, 14',
1842 'CY, 14',
1843 'CZ, 15',
1844 'DK, 13',
1845 'EE, 13',
1846 'ES, 14',
1847 'FI, 13',
1848 'FR, 15',
1849 'GB, 13',
1850 'GR, 15',
1851 'IT, 14',
1852 'LT, 14',
1853 'LV, 13',
1854 'MT, 13',
1855 'NO, 13',
1856 'PT, 13',
1857 'SE, 13',
1858 'US, 13'
1859 ]);
1860 set_config('agedigitalconsentmap', $ageofdigitalconsentmap);
1861 }
1862
1863 upgrade_main_savepoint(true, 2020061500.02);
1864 }
b764343e 1865
b6c7a25d
NM
1866 if ($oldversion < 2020062600.01) {
1867 // Add index to the token field in the external_tokens table.
1868 $table = new xmldb_table('external_tokens');
1869 $index = new xmldb_index('token', XMLDB_INDEX_NOTUNIQUE, ['token']);
1870
1871 if (!$dbman->index_exists($table, $index)) {
1872 $dbman->add_index($table, $index);
1873 }
1874
1875 upgrade_main_savepoint(true, 2020062600.01);
1876 }
1877
8acaa4e3
PH
1878 if ($oldversion < 2020071100.01) {
1879 // Clean up completion criteria records referring to NULL course prerequisites.
1880 $select = 'criteriatype = :type AND courseinstance IS NULL';
1881 $params = ['type' => 8]; // COMPLETION_CRITERIA_TYPE_COURSE.
1882
1883 $DB->delete_records_select('course_completion_criteria', $select, $params);
1884
1885 // Main savepoint reached.
1886 upgrade_main_savepoint(true, 2020071100.01);
1887 }
1888
d6ec2d3e
MG
1889 if ($oldversion < 2020072300.01) {
1890 // Restore and set the guest user if it has been previously removed via GDPR, or set to an nonexistent
1891 // user account.
1892 $currentguestuser = $DB->get_record('user', array('id' => $CFG->siteguest));
1893
1894 if (!$currentguestuser) {
1895 if (!$guest = $DB->get_record('user', array('username' => 'guest', 'mnethostid' => $CFG->mnet_localhost_id))) {
1896 // Create a guest user account.
1897 $guest = new stdClass();
1898 $guest->auth = 'manual';
1899 $guest->username = 'guest';
1900 $guest->password = hash_internal_user_password('guest');
1901 $guest->firstname = get_string('guestuser');
1902 $guest->lastname = ' ';
1903 $guest->email = 'root@localhost';
1904 $guest->description = get_string('guestuserinfo');
1905 $guest->mnethostid = $CFG->mnet_localhost_id;
1906 $guest->confirmed = 1;
1907 $guest->lang = $CFG->lang;
1908 $guest->timemodified= time();
1909 $guest->id = $DB->insert_record('user', $guest);
1910 }
1911 // Set the guest user.
1912 set_config('siteguest', $guest->id);
1913 }
1914
1915 // Main savepoint reached.
1916 upgrade_main_savepoint(true, 2020072300.01);
1917 }
1918
ef73bfbe 1919 if ($oldversion < 2021052500.01) {
fcb899b9
SL
1920 // Delete all user evidence files from users that have been deleted.
1921 $sql = "SELECT DISTINCT f.*
1922 FROM {files} f
1923 LEFT JOIN {context} c ON f.contextid = c.id
fcb899b9
SL
1924 WHERE f.component = :component
1925 AND f.filearea = :filearea
f968aaf7 1926 AND c.id IS NULL";
fcb899b9
SL
1927 $stalefiles = $DB->get_records_sql($sql, ['component' => 'core_competency', 'filearea' => 'userevidence']);
1928
1929 $fs = get_file_storage();
1930 foreach ($stalefiles as $stalefile) {
1931 $fs->get_file_instance($stalefile)->delete();
1932 }
1933
0dbeb974
EL
1934 upgrade_main_savepoint(true, 2021052500.01);
1935 }
1936
1937 if ($oldversion < 2021052500.02) {
1938
1939 // Define field timecreated to be added to task_adhoc.
1940 $table = new xmldb_table('task_adhoc');
1941 $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'blocking');
1942
1943 // Conditionally launch add field timecreated.
1944 if (!$dbman->field_exists($table, $field)) {
1945 $dbman->add_field($table, $field);
1946 }
1947
1948 // Main savepoint reached.
257b90d1 1949 upgrade_main_savepoint(true, 2021052500.02);
fcb899b9
SL
1950 }
1951
9aa9efbf 1952 if ($oldversion < 2021052500.04) {
9aa9efbf
VDF
1953 // Define field metadatasettings to be added to h5p_libraries.
1954 $table = new xmldb_table('h5p_libraries');
1955 $field = new xmldb_field('metadatasettings', XMLDB_TYPE_TEXT, null, null, null, null, null, 'coreminor');
1956
1957 // Conditionally launch add field metadatasettings.
1958 if (!$dbman->field_exists($table, $field)) {
1959 $dbman->add_field($table, $field);
1960 }
1961
1962 // Get installed library files that have no metadata settings value.
1963 $params = [
1964 'component' => 'core_h5p',
1965 'filearea' => 'libraries',
1966 'filename' => 'library.json',
1967 ];
1968 $sql = "SELECT l.id, f.id as fileid
1969 FROM {files} f
1970 LEFT JOIN {h5p_libraries} l ON f.itemid = l.id
1971 WHERE f.component = :component
1972 AND f.filearea = :filearea
1973 AND f.filename = :filename";
1974 $libraries = $DB->get_records_sql($sql, $params);
1975
1976 // Update metadatasettings field when the attribute is present in the library.json file.
1977 $fs = get_file_storage();
1978 foreach ($libraries as $library) {
1979 $jsonfile = $fs->get_file_by_id($library->fileid);
1980 $jsoncontent = json_decode($jsonfile->get_content());
1981 if (isset($jsoncontent->metadataSettings)) {
1982 unset($library->fileid);
1983 $library->metadatasettings = json_encode($jsoncontent->metadataSettings);
1984 $DB->update_record('h5p_libraries', $library);
1985 }
1986 }
1987
1988 // Main savepoint reached.
1989 upgrade_main_savepoint(true, 2021052500.04);
1990 }
1991
23517d90 1992 if ($oldversion < 2021052500.05) {
b465a541
MG
1993 // Define fields to be added to task_scheduled.
1994 $table = new xmldb_table('task_scheduled');
1995 $field = new xmldb_field('timestarted', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'disabled');
1996 if (!$dbman->field_exists($table, $field)) {
1997 $dbman->add_field($table, $field);
1998 }
1999 $field = new xmldb_field('hostname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'timestarted');
2000 if (!$dbman->field_exists($table, $field)) {
2001 $dbman->add_field($table, $field);
2002 }
2003 $field = new xmldb_field('pid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'hostname');
2004 if (!$dbman->field_exists($table, $field)) {
2005 $dbman->add_field($table, $field);
2006 }
2007
2008 // Define fields to be added to task_adhoc.
2009 $table = new xmldb_table('task_adhoc');
2010 $field = new xmldb_field('timestarted', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'blocking');
2011 if (!$dbman->field_exists($table, $field)) {
2012 $dbman->add_field($table, $field);
2013 }
2014 $field = new xmldb_field('hostname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'timestarted');
2015 if (!$dbman->field_exists($table, $field)) {
2016 $dbman->add_field($table, $field);
2017 }
2018 $field = new xmldb_field('pid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'hostname');
2019 if (!$dbman->field_exists($table, $field)) {
2020 $dbman->add_field($table, $field);
2021 }
2022
2023 // Define fields to be added to task_log.
2024 $table = new xmldb_table('task_log');
2025 $field = new xmldb_field('hostname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'output');
2026 if (!$dbman->field_exists($table, $field)) {
2027 $dbman->add_field($table, $field);
2028 }
2029 $field = new xmldb_field('pid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'hostname');
2030 if (!$dbman->field_exists($table, $field)) {
2031 $dbman->add_field($table, $field);
2032 }
2033
2034 // Main savepoint reached.
23517d90 2035 upgrade_main_savepoint(true, 2021052500.05);
b465a541
MG
2036 }
2037
e471d823 2038 if ($oldversion < 2021052500.06) {
adbe92ce
NN
2039 // Define table to store virus infected details.
2040 $table = new xmldb_table('infected_files');
2041
8e0e99e4 2042 // Adding fields to table infected_files.
adbe92ce
NN
2043 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2044 $table->add_field('filename', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
8e0e99e4
PB
2045 $table->add_field('quarantinedfile', XMLDB_TYPE_TEXT, null, null, null, null, null);
2046 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
adbe92ce
NN
2047 $table->add_field('reason', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
2048 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
2049
8e0e99e4 2050 // Adding keys to table infected_files.
adbe92ce 2051 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
8e0e99e4 2052 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
adbe92ce 2053
8e0e99e4 2054 // Conditionally launch create table for infected_files.
adbe92ce
NN
2055 if (!$dbman->table_exists($table)) {
2056 $dbman->create_table($table);
2057 }
e471d823 2058 upgrade_main_savepoint(true, 2021052500.06);
adbe92ce 2059 }
e471d823 2060
6d4e245b
SA
2061 if ($oldversion < 2021052500.13) {
2062 // Remove all the files with component='core_h5p' and filearea='editor' because they won't be used anymore.
2063 $fs = get_file_storage();
2064 $syscontext = context_system::instance();
2065 $fs->delete_area_files($syscontext->id, 'core_h5p', 'editor');
2066
2067 // Main savepoint reached.
2068 upgrade_main_savepoint(true, 2021052500.13);
2069 }
2070
5b8c646e
CV
2071 if ($oldversion < 2021052500.15) {
2072 // Copy From id captures the id of the source course when a new course originates from a restore
2073 // of another course on the same site.
2074 $table = new xmldb_table('course');
2075 $field = new xmldb_field('originalcourseid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2076
2077 if (!$dbman->field_exists($table, $field)) {
2078 $dbman->add_field($table, $field);
2079 }
2080
2081 // Main savepoint reached.
2082 upgrade_main_savepoint(true, 2021052500.15);
2083 }
2084
6502c13b
JD
2085 if ($oldversion < 2021052500.19) {
2086 // Define table oauth2_refresh_token to be created.
2087 $table = new xmldb_table('oauth2_refresh_token');
2088
2089 // Adding fields to table oauth2_refresh_token.
2090 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2091 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2092 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2093 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2094 $table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2095 $table->add_field('token', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
2096 $table->add_field('scopehash', XMLDB_TYPE_CHAR, 40, null, XMLDB_NOTNULL, null, null);
2097
2098 // Adding keys to table oauth2_refresh_token.
2099 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2100 $table->add_key('issueridkey', XMLDB_KEY_FOREIGN, ['issuerid'], 'oauth2_issuer', ['id']);
2101 $table->add_key('useridkey', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
2102
2103 // Adding indexes to table oauth2_refresh_token.
2104 $table->add_index('userid-issuerid-scopehash', XMLDB_INDEX_UNIQUE, array('userid', 'issuerid', 'scopehash'));
2105
2106 // Conditionally launch create table for oauth2_refresh_token.
2107 if (!$dbman->table_exists($table)) {
2108 $dbman->create_table($table);
2109 }
2110
2111 // Main savepoint reached.
2112 upgrade_main_savepoint(true, 2021052500.19);
2113 }
2114
b80d65e4
JM
2115 if ($oldversion < 2021052500.20) {
2116
2117 // Define index modulename-instance-eventtype (not unique) to be added to event.
2118 $table = new xmldb_table('event');
2119 $index = new xmldb_index('modulename-instance-eventtype', XMLDB_INDEX_NOTUNIQUE, ['modulename', 'instance', 'eventtype']);
2120
2121 // Conditionally launch add index modulename-instance-eventtype.
2122 if (!$dbman->index_exists($table, $index)) {
2123 $dbman->add_index($table, $index);
2124 }
2125
2126 // Define index modulename-instance (not unique) to be dropped form event.
2127 $table = new xmldb_table('event');
2128 $index = new xmldb_index('modulename-instance', XMLDB_INDEX_NOTUNIQUE, ['modulename', 'instance']);
2129
2130 // Conditionally launch drop index modulename-instance.
2131 if ($dbman->index_exists($table, $index)) {
2132 $dbman->drop_index($table, $index);
2133 }
2134
2135 // Main savepoint reached.
2136 upgrade_main_savepoint(true, 2021052500.20);
2137 }
2138
6171c4bb
SA
2139 if ($oldversion < 2021052500.24) {
2140 // Define fields tutorial and example to be added to h5p_libraries.
2141 $table = new xmldb_table('h5p_libraries');
2142
2143 // Add tutorial field.
2144 $field = new xmldb_field('tutorial', XMLDB_TYPE_TEXT, null, null, null, null, null, 'metadatasettings');
2145 if (!$dbman->field_exists($table, $field)) {
2146 $dbman->add_field($table, $field);
2147 }
2148
2149 // Add example field.
2150 $field = new xmldb_field('example', XMLDB_TYPE_TEXT, null, null, null, null, null, 'tutorial');
840bcd88 2151
6171c4bb
SA
2152 if (!$dbman->field_exists($table, $field)) {
2153 $dbman->add_field($table, $field);
2154 }
2155
2156 // Main savepoint reached.
2157 upgrade_main_savepoint(true, 2021052500.24);
2158 }
2159
4dcca1b0 2160 if ($oldversion < 2021052500.26) {
2161 // Delete orphaned course_modules_completion rows; these were not deleted properly
2162 // by remove_course_contents function.
a6edd14d
TH
2163 $DB->delete_records_select('course_modules_completion', "
2164 NOT EXISTS (
2165 SELECT 1
2166 FROM {course_modules} cm
2167 WHERE cm.id = {course_modules_completion}.coursemoduleid
2168 )");
4dcca1b0 2169 upgrade_main_savepoint(true, 2021052500.26);
2170 }
2171
33831f6e 2172 if ($oldversion < 2021052500.27) {
a0ffd0de
SG
2173 // Script to fix incorrect records of "hidden" field in existing grade items.
2174 $sql = "SELECT cm.instance, cm.course
2175 FROM {course_modules} cm
2176 JOIN {modules} m ON m.id = cm.module
2177 WHERE m.name = :module AND cm.visible = :visible";
2178 $hidequizlist = $DB->get_recordset_sql($sql, ['module' => 'quiz', 'visible' => 0]);
2179
2180 foreach ($hidequizlist as $hidequiz) {
2181 $params = [
2182 'itemmodule' => 'quiz',
2183 'courseid' => $hidequiz->course,
2184 'iteminstance' => $hidequiz->instance,
2185 ];
2186
2187 $DB->set_field('grade_items', 'hidden', 1, $params);
2188 }
2189 $hidequizlist->close();
2190
33831f6e 2191 upgrade_main_savepoint(true, 2021052500.27);
a0ffd0de
SG
2192 }
2193
3d0f28eb 2194 if ($oldversion < 2021052500.29) {
e412f302
MG
2195 // Get the current guest user which is also set as 'deleted'.
2196 $guestuser = $DB->get_record('user', ['id' => $CFG->siteguest, 'deleted' => 1]);
2197 // If there is a deleted guest user, reset the user to not be deleted and make sure the related
2198 // user context exists.
2199 if ($guestuser) {
2200 $guestuser->deleted = 0;
2201 $DB->update_record('user', $guestuser);
2202
2203 // Get the guest user context.
2204 $guestusercontext = $DB->get_record('context',
2205 ['contextlevel' => CONTEXT_USER, 'instanceid' => $guestuser->id]);
2206
2207 // If the guest user context does not exist, create it.
2208 if (!$guestusercontext) {
2209 $record = new stdClass();
2210 $record->contextlevel = CONTEXT_USER;
2211 $record->instanceid = $guestuser->id;
2212 $record->depth = 0;
2213 // The path is not known before insert.
2214 $record->path = null;
2215 $record->locked = 0;
2216
2217 $record->id = $DB->insert_record('context', $record);
2218
2219 // Update the path.
2220 $record->path = '/' . SYSCONTEXTID . '/' . $record->id;
2221 $record->depth = substr_count($record->path, '/');
2222 $DB->update_record('context', $record);
2223 }
2224 }
2225
2226 // Main savepoint reached.
3d0f28eb 2227 upgrade_main_savepoint(true, 2021052500.29);
e412f302
MG
2228 }
2229
284d0ae8 2230 if ($oldversion < 2021052500.30) {
cecd90ff
PH
2231 // Reset analytics model output dir if it's the default value.
2232 $modeloutputdir = get_config('analytics', 'modeloutputdir');
2233 if (strcasecmp($modeloutputdir, $CFG->dataroot . DIRECTORY_SEPARATOR . 'models') == 0) {
2234 set_config('modeloutputdir', '', 'analytics');
2235 }
2236
2237 // Main savepoint reached.
284d0ae8 2238 upgrade_main_savepoint(true, 2021052500.30);
cecd90ff
PH
2239 }
2240
840bcd88
MH
2241 if ($oldversion < 2021052500.32) {
2242 // Define field downloadcontent to be added to course.
2243 $table = new xmldb_table('course');
2244 $field = new xmldb_field('downloadcontent', XMLDB_TYPE_INTEGER, '1', null, null, null, null, 'visibleold');
2245
2246 if (!$dbman->field_exists($table, $field)) {
2247 $dbman->add_field($table, $field);
2248 }
2249
2250 // Main savepoint reached.
2251 upgrade_main_savepoint(true, 2021052500.32);
2252 }
2253
5deb0dad 2254 if ($oldversion < 2021052500.33) {
3cae9421 2255 $table = new xmldb_table('badge_backpack');
3cae9421 2256
c7d9b129
SA
2257 // There is no key_exists, so test the equivalent index.
2258 $oldindex = new xmldb_index('backpackcredentials', XMLDB_KEY_UNIQUE, ['userid', 'externalbackpackid']);
2259 if (!$dbman->index_exists($table, $oldindex)) {
2260 // All external backpack providers/hosts are now exclusively stored in badge_external_backpack.
2261 // All credentials are stored in badge_backpack and are unique per user, backpack.
2262 $uniquekey = new xmldb_key('backpackcredentials', XMLDB_KEY_UNIQUE, ['userid', 'externalbackpackid']);
3cae9421
PD
2263 $dbman->add_key($table, $uniquekey);
2264 }
2265
3cae9421 2266 // Drop the password field as this is moved to badge_backpack.
1c4620bc 2267 $table = new xmldb_table('badge_external_backpack');
3cae9421
PD
2268 $field = new xmldb_field('password', XMLDB_TYPE_CHAR, '50');
2269 if ($dbman->field_exists($table, $field)) {
c7d9b129
SA
2270 // If there is a current backpack set then copy it across to the new structure.
2271 if ($CFG->badges_defaultissuercontact) {
2272 // Get the currently used site backpacks.
2273 $records = $DB->get_records_select('badge_external_backpack', "password IS NOT NULL AND password != ''");
2274 $backpack = [
2275 'userid' => '0',
2276 'email' => $CFG->badges_defaultissuercontact,
2277 'backpackuid' => -1
2278 ];
2279
2280 // Create records corresponding to the site backpacks.
2281 foreach ($records as $record) {
2282 $backpack['password'] = $record->password;
2283 $backpack['externalbackpackid'] = $record->id;
2284 $DB->insert_record('badge_backpack', (object) $backpack);
2285 }
2286 }
2287
3cae9421 2288 $dbman->drop_field($table, $field);
931f36ce 2289 }
df177126
PD
2290
2291 // Main savepoint reached.
2292 upgrade_main_savepoint(true, 2021052500.33);
931f36ce
AN
2293 }
2294
d5be2887 2295 if ($oldversion < 2021052500.36) {
6ff3087f
MG
2296 // Define table payment_accounts to be created.
2297 $table = new xmldb_table('payment_accounts');
2298
2299 // Adding fields to table payment_accounts.
2300 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2301 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
2302 $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null);
2303 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2304 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
410973cf 2305 $table->add_field('archived', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
6ff3087f
MG
2306 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2307 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2308
2309 // Adding keys to table payment_accounts.
2310 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2311
2312 // Conditionally launch create table for payment_accounts.
2313 if (!$dbman->table_exists($table)) {
2314 $dbman->create_table($table);
2315 }
2316
2317 // Define table payment_gateways to be created.
2318 $table = new xmldb_table('payment_gateways');
2319
2320 // Adding fields to table payment_gateways.
2321 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2322 $table->add_field('accountid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2323 $table->add_field('gateway', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
2324 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1');
2325 $table->add_field('config', XMLDB_TYPE_TEXT, null, null, null, null, null);
2326 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2327 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2328
2329 // Adding keys to table payment_gateways.
2330 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2331 $table->add_key('accountid', XMLDB_KEY_FOREIGN, ['accountid'], 'payment_accounts', ['id']);
2332
2333 // Conditionally launch create table for payment_gateways.
2334 if (!$dbman->table_exists($table)) {
2335 $dbman->create_table($table);
2336 }
2337
410973cf 2338 // Define table payments to be created.
61766b3d 2339 $table = new xmldb_table('payments');
61766b3d 2340
410973cf
SR
2341 // Adding fields to table payments.
2342 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2343 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
2344 $table->add_field('paymentarea', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL, null, null);
d5a9d6e5 2345 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
410973cf
SR
2346 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2347 $table->add_field('amount', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null);
2348 $table->add_field('currency', XMLDB_TYPE_CHAR, '3', null, XMLDB_NOTNULL, null, null);
2349 $table->add_field('accountid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
2350 $table->add_field('gateway', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
2351 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
2352 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
61766b3d 2353
410973cf
SR
2354 // Adding keys to table payments.
2355 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2356 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
2357 $table->add_key('accountid', XMLDB_KEY_FOREIGN, ['accountid'], 'payment_accounts', ['id']);
61766b3d 2358
410973cf
SR
2359 // Adding indexes to table payments.
2360 $table->add_index('gateway', XMLDB_INDEX_NOTUNIQUE, ['gateway']);
d5a9d6e5 2361 $table->add_index('component-paymentarea-itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'paymentarea', 'itemid']);
61766b3d 2362
410973cf
SR
2363 // Conditionally launch create table for payments.
2364 if (!$dbman->table_exists($table)) {
2365 $dbman->create_table($table);
1c4620bc 2366 }
1c4620bc
P
2367
2368 // Main savepoint reached.
931f36ce 2369 upgrade_main_savepoint(true, 2021052500.36);
1c4620bc
P
2370 }
2371
8e3031ae
PD
2372 if ($oldversion < 2021052500.42) {
2373 // Get all lessons that are set with a completion criteria of 'requires grade' but with no grade type set.
2374 $sql = "SELECT cm.id
2375 FROM {course_modules} cm
2376 JOIN {lesson} l ON l.id = cm.instance
2377 JOIN {modules} m ON m.id = cm.module
2378 WHERE m.name = :name AND cm.completiongradeitemnumber IS NOT NULL AND l.grade = :grade";
2379
2380 do {
2381 if ($invalidconfigrations = $DB->get_records_sql($sql, ['name' => 'lesson', 'grade' => 0], 0, 1000)) {
2382 list($insql, $inparams) = $DB->get_in_or_equal(array_keys($invalidconfigrations), SQL_PARAMS_NAMED);
2383 $DB->set_field_select('course_modules', 'completiongradeitemnumber', null, "id $insql", $inparams);
2384 }
2385 } while ($invalidconfigrations);
2386
2387 upgrade_main_savepoint(true, 2021052500.42);
2388 }
2389
cd4d3879 2390 if ($oldversion < 2021052500.55) {
e8bd3b41
SL
2391 $DB->delete_records_select('event', "eventtype = 'category' AND categoryid = 0 AND userid <> 0");
2392
cd4d3879 2393 upgrade_main_savepoint(true, 2021052500.55);
e8bd3b41
SL
2394 }
2395
3776fbaf
FM
2396 if ($oldversion < 2021052500.59) {
2397 // Define field visibility to be added to contentbank_content.
2398 $table = new xmldb_table('contentbank_content');
2399 $field = new xmldb_field('visibility', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'contextid');
2400
2401 // Conditionally launch add field visibility.
2402 if (!$dbman->field_exists($table, $field)) {
2403 $dbman->add_field($table, $field);
2404 }
2405
2406 // Main savepoint reached.
2407 upgrade_main_savepoint(true, 2021052500.59);
2408 }
2409
3d117c19 2410 if ($oldversion < 2021052500.60) {
3aed37ee
FM
2411
2412 // We are going to remove the field 'hidepicture' from the groups
2413 // so we need to remove the pictures from those groups. But we prevent
2414 // the execution twice because this could be executed again when upgrading
2415 // to different versions.
2416 if ($dbman->field_exists('groups', 'hidepicture')) {
2417
2418 $sql = "SELECT g.id, g.courseid, ctx.id AS contextid
2419 FROM {groups} g
2420 JOIN {context} ctx
2421 ON ctx.instanceid = g.courseid
2422 AND ctx.contextlevel = :contextlevel
2423 WHERE g.hidepicture = 1";
2424
2425 // Selecting all the groups that have hide picture enabled, and organising them by context.
2426 $groupctx = [];
2427 $records = $DB->get_recordset_sql($sql, ['contextlevel' => CONTEXT_COURSE]);
2428 foreach ($records as $record) {
2429 if (!isset($groupctx[$record->contextid])) {
2430 $groupctx[$record->contextid] = [];
2431 }
2432 $groupctx[$record->contextid][] = $record->id;
2433 }
2434 $records->close();
2435
2436 // Deleting the group files.
2437 $fs = get_file_storage();
2438 foreach ($groupctx as $contextid => $groupids) {
2439 list($in, $inparams) = $DB->get_in_or_equal($groupids, SQL_PARAMS_NAMED);
2440 $fs->delete_area_files_select($contextid, 'group', 'icon', $in, $inparams);
2441 }
2442
2443 // Updating the database to remove picture from all those groups.
2444 $sql = "UPDATE {groups} SET picture = :pic WHERE hidepicture = :hide";
2445 $DB->execute($sql, ['pic' => 0, 'hide' => 1]);
2446 }
2447
2448 // Define field hidepicture to be dropped from groups.
2449 $table = new xmldb_table('groups');
2450 $field = new xmldb_field('hidepicture');
2451
2452 // Conditionally launch drop field hidepicture.
2453 if ($dbman->field_exists($table, $field)) {
2454 $dbman->drop_field($table, $field);
2455 }
2456
2457 // Main savepoint reached.
3d117c19 2458 upgrade_main_savepoint(true, 2021052500.60);
3aed37ee
FM
2459 }
2460
9e5655b7
SA
2461 if ($oldversion < 2021052500.64) {
2462 // Get all the external backpacks and update the sortorder column, to avoid repeated/wrong values. As sortorder was not
2463 // used since now, the id column will be the criteria to follow for re-ordering them with a valid value.
2464 $i = 1;
2465 $records = $DB->get_records('badge_external_backpack', null, 'id ASC');
2466 foreach ($records as $record) {
2467 $record->sortorder = $i++;
2468 $DB->update_record('badge_external_backpack', $record);
2469 }
2470
2471 upgrade_main_savepoint(true, 2021052500.64);
2472 }
2473
49c1d41a
SA
2474 if ($oldversion < 2021052500.67) {
2475 // The $CFG->badges_site_backpack setting has been removed because it's not required anymore. From now, the default backpack
2476 // will be the one with lower sortorder value.
2477 unset_config('badges_site_backpack');
2478
2479 upgrade_main_savepoint(true, 2021052500.67);
2480 }
2481
5066c602
SA
2482 if ($oldversion < 2021052500.69) {
2483
2484 // Define field type to be added to oauth2_issuer.
2485 $table = new xmldb_table('oauth2_issuer');
2486 $field = new xmldb_field('servicetype', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'requireconfirmation');
2487
2488 // Conditionally launch add field type.
2489 if (!$dbman->field_exists($table, $field)) {
2490 $dbman->add_field($table, $field);
2491 }
2492
2493 // Set existing values to the proper servicetype value.
2494 // It's not critical if the servicetype column doesn't contain the proper value for Google, Microsoft, Facebook or
2495 // Nextcloud services because, for now, this value is used for services using different discovery method.
2496 // However, let's try to upgrade it using the default value for the baseurl or image. If any of these default values
2497 // have been changed, the servicetype column will remain NULL.
2498 $recordset = $DB->get_recordset('oauth2_issuer');
2499 foreach ($recordset as $record) {
2500 if ($record->baseurl == 'https://accounts.google.com/') {
2501 $record->servicetype = 'google';
2502 $DB->update_record('oauth2_issuer', $record);
2503 } else if ($record->image == 'https://www.microsoft.com/favicon.ico') {
2504 $record->servicetype = 'microsoft';
2505 $DB->update_record('oauth2_issuer', $record);
2506 } else if ($record->image == 'https://facebookbrand.com/wp-content/uploads/2016/05/flogo_rgb_hex-brc-site-250.png') {
2507 $record->servicetype = 'facebook';
2508 $DB->update_record('oauth2_issuer', $record);
2509 } else if ($record->image == 'https://nextcloud.com/wp-content/themes/next/assets/img/common/favicon.png?x16328') {
2510 $record->servicetype = 'nextcloud';
2511 $DB->update_record('oauth2_issuer', $record);
2512 }
2513 }
2514 $recordset->close();
2515
2516 // Main savepoint reached.
2517 upgrade_main_savepoint(true, 2021052500.69);
2518 }
2519
680018c9
SL
2520 if ($oldversion < 2021052500.74) {
2521 // Define field 'showactivitydates' to be added to course table.
2522 $table = new xmldb_table('course');
2523 $field = new xmldb_field('showactivitydates', XMLDB_TYPE_INTEGER, '1', null,
2524 XMLDB_NOTNULL, null, '0', 'originalcourseid');
2525
2526 if (!$dbman->field_exists($table, $field)) {
2527 $dbman->add_field($table, $field);
2528 }
2529
2530 // Main savepoint reached.
2531 upgrade_main_savepoint(true, 2021052500.74);
2532 }
2533
a4f7c1d9
SL
2534 if ($oldversion < 2021052500.75) {
2535 // Define field 'showcompletionconditions' to be added to course.
2536 $table = new xmldb_table('course');
2537 $field = new xmldb_field('showcompletionconditions', XMLDB_TYPE_INTEGER, '1', null,
2538 XMLDB_NOTNULL, null, '1', 'completionnotify');
2539
2540 if (!$dbman->field_exists($table, $field)) {
2541 $dbman->add_field($table, $field);
2542 }
2543
2544 // Main savepoint reached.
2545 upgrade_main_savepoint(true, 2021052500.75);
2546 }
2547
d3d3b3bd
SA
2548 if ($oldversion < 2021052500.78) {
2549
2550 // Define field enabled to be added to h5p_libraries.
2551 $table = new xmldb_table('h5p_libraries');
2552 $field = new xmldb_field('enabled', XMLDB_TYPE_INTEGER, '1', null, null, null, '1', 'example');
2553
2554 // Conditionally launch add field enabled.
2555 if (!$dbman->field_exists($table, $field)) {
2556 $dbman->add_field($table, $field);
2557 }
2558
2559 // Main savepoint reached.
2560 upgrade_main_savepoint(true, 2021052500.78);
2561 }
2562
610b339c 2563 if ($oldversion < 2021052500.83) {
0152fdbd
MG
2564
2565 // Define field loginpagename to be added to oauth2_issuer.
2566 $table = new xmldb_table('oauth2_issuer');
2567 $field = new xmldb_field('loginpagename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'servicetype');
2568
2569 // Conditionally launch add field loginpagename.
2570 if (!$dbman->field_exists($table, $field)) {
2571 $dbman->add_field($table, $field);
2572 }
2573
2574 // Main savepoint reached.
610b339c 2575 upgrade_main_savepoint(true, 2021052500.83);
0152fdbd
MG
2576 }
2577
8a53fe7f 2578 if ($oldversion < 2021052500.84) {
f9e1c258
BB
2579 require_once($CFG->dirroot . '/user/profile/field/social/upgradelib.php');
2580 $table = new xmldb_table('user');
2581 $tablecolumns = ['icq', 'skype', 'aim', 'yahoo', 'msn', 'url'];
2582
2583 foreach ($tablecolumns as $column) {
2584 $field = new xmldb_field($column);
2585 if ($dbman->field_exists($table, $field)) {
2586 user_profile_social_moveto_profilefield($column);
2587 $dbman->drop_field($table, $field);
2588 }
2589 }
2590
2591 // Update all module availability if it relies on the old user fields.
2592 user_profile_social_update_module_availability();
2593
2594 // Remove field mapping for oauth2.
2595 $DB->delete_records('oauth2_user_field_mapping', array('internalfield' => 'url'));
2596
2597 // Main savepoint reached.
8a53fe7f 2598 upgrade_main_savepoint(true, 2021052500.84);
f9e1c258
BB
2599 }
2600
5b028284
SL
2601 if ($oldversion < 2021052500.85) {
2602 require_once($CFG->libdir . '/db/upgradelib.php');
2603
2604 // Check if this site has executed the problematic upgrade steps.
2605 $needsfixing = upgrade_calendar_site_status(false);
2606
2607 // Only queue the task if this site has been affected by the problematic upgrade step.
2608 if ($needsfixing) {
2609
2610 // Create adhoc task to search and recover orphaned calendar events.
2611 $record = new \stdClass();
2612 $record->classname = '\core\task\calendar_fix_orphaned_events';
2613
2614 // Next run time based from nextruntime computation in \core\task\manager::queue_adhoc_task().
2615 $nextruntime = time() - 1;
2616 $record->nextruntime = $nextruntime;
2617 $DB->insert_record('task_adhoc', $record);
2618 }
2619
2620 // Main savepoint reached.
2621 upgrade_main_savepoint(true, 2021052500.85);
2622 }
2623
fca42002
JP
2624 if ($oldversion < 2021052500.87) {
2625 // Changing the default of field showcompletionconditions on table course to 0.
2626 $table = new xmldb_table('course');
2627 $field = new xmldb_field('showcompletionconditions', XMLDB_TYPE_INTEGER, '1', null, null, null, null, 'showactivitydates');
2628
2629 // Launch change of nullability for field showcompletionconditions.
2630 $dbman->change_field_notnull($table, $field);
2631
2632 // Launch change of default for field showcompletionconditions.
2633 $dbman->change_field_default($table, $field);
2634
2635 // Set showcompletionconditions to null for courses which don't track completion.
2636 $sql = "UPDATE {course}
2637 SET showcompletionconditions = null
2638 WHERE enablecompletion <> 1";
2639 $DB->execute($sql);
2640
2641 // Main savepoint reached.
2642 upgrade_main_savepoint(true, 2021052500.87);
2643 }
2644
430746d3
IT
2645 if ($oldversion < 2021052500.90) {
2646 // Remove usemodchooser user preference for every user.
2647 $DB->delete_records('user_preferences', ['name' => 'usemodchooser']);
2648
2649 // Main savepoint reached.
2650 upgrade_main_savepoint(true, 2021052500.90);
2651 }
2652
0f5e9aa7 2653 if ($oldversion < 2021060200.00) {
ee3c6ad3
MG
2654
2655 // Define index name (not unique) to be added to user_preferences.
2656 $table = new xmldb_table('user_preferences');
2657 $index = new xmldb_index('name', XMLDB_INDEX_NOTUNIQUE, ['name']);
2658
2659 // Conditionally launch add index name.
2660 if (!$dbman->index_exists($table, $index)) {
2661 $dbman->add_index($table, $index);
2662 }
2663
2664 // Main savepoint reached.
0f5e9aa7 2665 upgrade_main_savepoint(true, 2021060200.00);
ee3c6ad3
MG
2666 }
2667
7782eeb5 2668 if ($oldversion < 2021060900.00) {
8e71f6b1
PD
2669 // Update the externalfield to be larger.
2670 $table = new xmldb_table('oauth2_user_field_mapping');
2671 $field = new xmldb_field('externalfield', XMLDB_TYPE_CHAR, '500', null, XMLDB_NOTNULL, false, null, 'issuerid');
2672 $dbman->change_field_type($table, $field);
2673
2674 // Main savepoint reached.
7782eeb5 2675 upgrade_main_savepoint(true, 2021060900.00);
8e71f6b1
PD
2676 }
2677
a4cdd6d2 2678 return true;
51003653 2679}