on-demand release 4.2dev+
[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
fa269897
EL
95 // allowed version to upgrade from (v3.11.8 right now).
96 if ($oldversion < 2021051708) {
e8c82aac 97 // Just in case somebody hacks upgrade scripts or env, we really can not continue.
fa269897 98 echo("You need to upgrade to 3.11.8 or higher first!\n");
5c79b8ed 99 exit(1);
e8c82aac 100 // Note this savepoint is 100% unreachable, but needed to pass the upgrade checks.
fa269897 101 upgrade_main_savepoint(true, 2021051708);
d6ec2d3e
MG
102 }
103
ef73bfbe 104 if ($oldversion < 2021052500.01) {
fcb899b9
SL
105 // Delete all user evidence files from users that have been deleted.
106 $sql = "SELECT DISTINCT f.*
107 FROM {files} f
108 LEFT JOIN {context} c ON f.contextid = c.id
fcb899b9
SL
109 WHERE f.component = :component
110 AND f.filearea = :filearea
f968aaf7 111 AND c.id IS NULL";
fcb899b9
SL
112 $stalefiles = $DB->get_records_sql($sql, ['component' => 'core_competency', 'filearea' => 'userevidence']);
113
114 $fs = get_file_storage();
115 foreach ($stalefiles as $stalefile) {
116 $fs->get_file_instance($stalefile)->delete();
117 }
118
0dbeb974
EL
119 upgrade_main_savepoint(true, 2021052500.01);
120 }
121
122 if ($oldversion < 2021052500.02) {
123
124 // Define field timecreated to be added to task_adhoc.
125 $table = new xmldb_table('task_adhoc');
126 $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'blocking');
127
128 // Conditionally launch add field timecreated.
129 if (!$dbman->field_exists($table, $field)) {
130 $dbman->add_field($table, $field);
131 }
132
133 // Main savepoint reached.
257b90d1 134 upgrade_main_savepoint(true, 2021052500.02);
fcb899b9
SL
135 }
136
9aa9efbf 137 if ($oldversion < 2021052500.04) {
9aa9efbf
VDF
138 // Define field metadatasettings to be added to h5p_libraries.
139 $table = new xmldb_table('h5p_libraries');
140 $field = new xmldb_field('metadatasettings', XMLDB_TYPE_TEXT, null, null, null, null, null, 'coreminor');
141
142 // Conditionally launch add field metadatasettings.
143 if (!$dbman->field_exists($table, $field)) {
144 $dbman->add_field($table, $field);
145 }
146
147 // Get installed library files that have no metadata settings value.
148 $params = [
149 'component' => 'core_h5p',
150 'filearea' => 'libraries',
151 'filename' => 'library.json',
152 ];
153 $sql = "SELECT l.id, f.id as fileid
154 FROM {files} f
155 LEFT JOIN {h5p_libraries} l ON f.itemid = l.id
156 WHERE f.component = :component
157 AND f.filearea = :filearea
158 AND f.filename = :filename";
159 $libraries = $DB->get_records_sql($sql, $params);
160
161 // Update metadatasettings field when the attribute is present in the library.json file.
162 $fs = get_file_storage();
163 foreach ($libraries as $library) {
164 $jsonfile = $fs->get_file_by_id($library->fileid);
165 $jsoncontent = json_decode($jsonfile->get_content());
166 if (isset($jsoncontent->metadataSettings)) {
167 unset($library->fileid);
168 $library->metadatasettings = json_encode($jsoncontent->metadataSettings);
169 $DB->update_record('h5p_libraries', $library);
170 }
171 }
172
173 // Main savepoint reached.
174 upgrade_main_savepoint(true, 2021052500.04);
175 }
176
23517d90 177 if ($oldversion < 2021052500.05) {
b465a541
MG
178 // Define fields to be added to task_scheduled.
179 $table = new xmldb_table('task_scheduled');
180 $field = new xmldb_field('timestarted', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'disabled');
181 if (!$dbman->field_exists($table, $field)) {
182 $dbman->add_field($table, $field);
183 }
184 $field = new xmldb_field('hostname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'timestarted');
185 if (!$dbman->field_exists($table, $field)) {
186 $dbman->add_field($table, $field);
187 }
188 $field = new xmldb_field('pid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'hostname');
189 if (!$dbman->field_exists($table, $field)) {
190 $dbman->add_field($table, $field);
191 }
192
193 // Define fields to be added to task_adhoc.
194 $table = new xmldb_table('task_adhoc');
195 $field = new xmldb_field('timestarted', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'blocking');
196 if (!$dbman->field_exists($table, $field)) {
197 $dbman->add_field($table, $field);
198 }
199 $field = new xmldb_field('hostname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'timestarted');
200 if (!$dbman->field_exists($table, $field)) {
201 $dbman->add_field($table, $field);
202 }
203 $field = new xmldb_field('pid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'hostname');
204 if (!$dbman->field_exists($table, $field)) {
205 $dbman->add_field($table, $field);
206 }
207
208 // Define fields to be added to task_log.
209 $table = new xmldb_table('task_log');
210 $field = new xmldb_field('hostname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'output');
211 if (!$dbman->field_exists($table, $field)) {
212 $dbman->add_field($table, $field);
213 }
214 $field = new xmldb_field('pid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'hostname');
215 if (!$dbman->field_exists($table, $field)) {
216 $dbman->add_field($table, $field);
217 }
218
219 // Main savepoint reached.
23517d90 220 upgrade_main_savepoint(true, 2021052500.05);
b465a541
MG
221 }
222
e471d823 223 if ($oldversion < 2021052500.06) {
adbe92ce
NN
224 // Define table to store virus infected details.
225 $table = new xmldb_table('infected_files');
226
8e0e99e4 227 // Adding fields to table infected_files.
adbe92ce
NN
228 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
229 $table->add_field('filename', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
8e0e99e4
PB
230 $table->add_field('quarantinedfile', XMLDB_TYPE_TEXT, null, null, null, null, null);
231 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
adbe92ce
NN
232 $table->add_field('reason', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
233 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
234
8e0e99e4 235 // Adding keys to table infected_files.
adbe92ce 236 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
8e0e99e4 237 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
adbe92ce 238
8e0e99e4 239 // Conditionally launch create table for infected_files.
adbe92ce
NN
240 if (!$dbman->table_exists($table)) {
241 $dbman->create_table($table);
242 }
e471d823 243 upgrade_main_savepoint(true, 2021052500.06);
adbe92ce 244 }
e471d823 245
6d4e245b
SA
246 if ($oldversion < 2021052500.13) {
247 // Remove all the files with component='core_h5p' and filearea='editor' because they won't be used anymore.
248 $fs = get_file_storage();
249 $syscontext = context_system::instance();
250 $fs->delete_area_files($syscontext->id, 'core_h5p', 'editor');
251
252 // Main savepoint reached.
253 upgrade_main_savepoint(true, 2021052500.13);
254 }
255
5b8c646e
CV
256 if ($oldversion < 2021052500.15) {
257 // Copy From id captures the id of the source course when a new course originates from a restore
258 // of another course on the same site.
259 $table = new xmldb_table('course');
260 $field = new xmldb_field('originalcourseid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
261
262 if (!$dbman->field_exists($table, $field)) {
263 $dbman->add_field($table, $field);
264 }
265
266 // Main savepoint reached.
267 upgrade_main_savepoint(true, 2021052500.15);
268 }
269
6502c13b
JD
270 if ($oldversion < 2021052500.19) {
271 // Define table oauth2_refresh_token to be created.
272 $table = new xmldb_table('oauth2_refresh_token');
273
274 // Adding fields to table oauth2_refresh_token.
275 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
276 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
277 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
278 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
279 $table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
280 $table->add_field('token', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
281 $table->add_field('scopehash', XMLDB_TYPE_CHAR, 40, null, XMLDB_NOTNULL, null, null);
282
283 // Adding keys to table oauth2_refresh_token.
284 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
285 $table->add_key('issueridkey', XMLDB_KEY_FOREIGN, ['issuerid'], 'oauth2_issuer', ['id']);
286 $table->add_key('useridkey', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
287
288 // Adding indexes to table oauth2_refresh_token.
289 $table->add_index('userid-issuerid-scopehash', XMLDB_INDEX_UNIQUE, array('userid', 'issuerid', 'scopehash'));
290
291 // Conditionally launch create table for oauth2_refresh_token.
292 if (!$dbman->table_exists($table)) {
293 $dbman->create_table($table);
294 }
295
296 // Main savepoint reached.
297 upgrade_main_savepoint(true, 2021052500.19);
298 }
299
b80d65e4
JM
300 if ($oldversion < 2021052500.20) {
301
302 // Define index modulename-instance-eventtype (not unique) to be added to event.
303 $table = new xmldb_table('event');
304 $index = new xmldb_index('modulename-instance-eventtype', XMLDB_INDEX_NOTUNIQUE, ['modulename', 'instance', 'eventtype']);
305
306 // Conditionally launch add index modulename-instance-eventtype.
307 if (!$dbman->index_exists($table, $index)) {
308 $dbman->add_index($table, $index);
309 }
310
311 // Define index modulename-instance (not unique) to be dropped form event.
312 $table = new xmldb_table('event');
313 $index = new xmldb_index('modulename-instance', XMLDB_INDEX_NOTUNIQUE, ['modulename', 'instance']);
314
315 // Conditionally launch drop index modulename-instance.
316 if ($dbman->index_exists($table, $index)) {
317 $dbman->drop_index($table, $index);
318 }
319
320 // Main savepoint reached.
321 upgrade_main_savepoint(true, 2021052500.20);
322 }
323
6171c4bb
SA
324 if ($oldversion < 2021052500.24) {
325 // Define fields tutorial and example to be added to h5p_libraries.
326 $table = new xmldb_table('h5p_libraries');
327
328 // Add tutorial field.
329 $field = new xmldb_field('tutorial', XMLDB_TYPE_TEXT, null, null, null, null, null, 'metadatasettings');
330 if (!$dbman->field_exists($table, $field)) {
331 $dbman->add_field($table, $field);
332 }
333
334 // Add example field.
335 $field = new xmldb_field('example', XMLDB_TYPE_TEXT, null, null, null, null, null, 'tutorial');
840bcd88 336
6171c4bb
SA
337 if (!$dbman->field_exists($table, $field)) {
338 $dbman->add_field($table, $field);
339 }
340
341 // Main savepoint reached.
342 upgrade_main_savepoint(true, 2021052500.24);
343 }
344
4dcca1b0 345 if ($oldversion < 2021052500.26) {
346 // Delete orphaned course_modules_completion rows; these were not deleted properly
347 // by remove_course_contents function.
a6edd14d
TH
348 $DB->delete_records_select('course_modules_completion', "
349 NOT EXISTS (
350 SELECT 1
351 FROM {course_modules} cm
352 WHERE cm.id = {course_modules_completion}.coursemoduleid
353 )");
4dcca1b0 354 upgrade_main_savepoint(true, 2021052500.26);
355 }
356
33831f6e 357 if ($oldversion < 2021052500.27) {
a0ffd0de
SG
358 // Script to fix incorrect records of "hidden" field in existing grade items.
359 $sql = "SELECT cm.instance, cm.course
360 FROM {course_modules} cm
361 JOIN {modules} m ON m.id = cm.module
362 WHERE m.name = :module AND cm.visible = :visible";
363 $hidequizlist = $DB->get_recordset_sql($sql, ['module' => 'quiz', 'visible' => 0]);
364
365 foreach ($hidequizlist as $hidequiz) {
366 $params = [
367 'itemmodule' => 'quiz',
368 'courseid' => $hidequiz->course,
369 'iteminstance' => $hidequiz->instance,
370 ];
371
372 $DB->set_field('grade_items', 'hidden', 1, $params);
373 }
374 $hidequizlist->close();
375
33831f6e 376 upgrade_main_savepoint(true, 2021052500.27);
a0ffd0de
SG
377 }
378
3d0f28eb 379 if ($oldversion < 2021052500.29) {
e412f302
MG
380 // Get the current guest user which is also set as 'deleted'.
381 $guestuser = $DB->get_record('user', ['id' => $CFG->siteguest, 'deleted' => 1]);
382 // If there is a deleted guest user, reset the user to not be deleted and make sure the related
383 // user context exists.
384 if ($guestuser) {
385 $guestuser->deleted = 0;
386 $DB->update_record('user', $guestuser);
387
388 // Get the guest user context.
389 $guestusercontext = $DB->get_record('context',
390 ['contextlevel' => CONTEXT_USER, 'instanceid' => $guestuser->id]);
391
392 // If the guest user context does not exist, create it.
393 if (!$guestusercontext) {
394 $record = new stdClass();
395 $record->contextlevel = CONTEXT_USER;
396 $record->instanceid = $guestuser->id;
397 $record->depth = 0;
398 // The path is not known before insert.
399 $record->path = null;
400 $record->locked = 0;
401
402 $record->id = $DB->insert_record('context', $record);
403
404 // Update the path.
405 $record->path = '/' . SYSCONTEXTID . '/' . $record->id;
406 $record->depth = substr_count($record->path, '/');
407 $DB->update_record('context', $record);
408 }
409 }
410
411 // Main savepoint reached.
3d0f28eb 412 upgrade_main_savepoint(true, 2021052500.29);
e412f302
MG
413 }
414
284d0ae8 415 if ($oldversion < 2021052500.30) {
cecd90ff
PH
416 // Reset analytics model output dir if it's the default value.
417 $modeloutputdir = get_config('analytics', 'modeloutputdir');
418 if (strcasecmp($modeloutputdir, $CFG->dataroot . DIRECTORY_SEPARATOR . 'models') == 0) {
419 set_config('modeloutputdir', '', 'analytics');
420 }
421
422 // Main savepoint reached.
284d0ae8 423 upgrade_main_savepoint(true, 2021052500.30);
cecd90ff
PH
424 }
425
840bcd88
MH
426 if ($oldversion < 2021052500.32) {
427 // Define field downloadcontent to be added to course.
428 $table = new xmldb_table('course');
429 $field = new xmldb_field('downloadcontent', XMLDB_TYPE_INTEGER, '1', null, null, null, null, 'visibleold');
430
431 if (!$dbman->field_exists($table, $field)) {
432 $dbman->add_field($table, $field);
433 }
434
435 // Main savepoint reached.
436 upgrade_main_savepoint(true, 2021052500.32);
437 }
438
5deb0dad 439 if ($oldversion < 2021052500.33) {
3cae9421 440 $table = new xmldb_table('badge_backpack');
3cae9421 441
c7d9b129
SA
442 // There is no key_exists, so test the equivalent index.
443 $oldindex = new xmldb_index('backpackcredentials', XMLDB_KEY_UNIQUE, ['userid', 'externalbackpackid']);
444 if (!$dbman->index_exists($table, $oldindex)) {
445 // All external backpack providers/hosts are now exclusively stored in badge_external_backpack.
446 // All credentials are stored in badge_backpack and are unique per user, backpack.
447 $uniquekey = new xmldb_key('backpackcredentials', XMLDB_KEY_UNIQUE, ['userid', 'externalbackpackid']);
3cae9421
PD
448 $dbman->add_key($table, $uniquekey);
449 }
450
3cae9421 451 // Drop the password field as this is moved to badge_backpack.
1c4620bc 452 $table = new xmldb_table('badge_external_backpack');
3cae9421
PD
453 $field = new xmldb_field('password', XMLDB_TYPE_CHAR, '50');
454 if ($dbman->field_exists($table, $field)) {
c7d9b129
SA
455 // If there is a current backpack set then copy it across to the new structure.
456 if ($CFG->badges_defaultissuercontact) {
457 // Get the currently used site backpacks.
458 $records = $DB->get_records_select('badge_external_backpack', "password IS NOT NULL AND password != ''");
459 $backpack = [
460 'userid' => '0',
461 'email' => $CFG->badges_defaultissuercontact,
462 'backpackuid' => -1
463 ];
464
465 // Create records corresponding to the site backpacks.
466 foreach ($records as $record) {
467 $backpack['password'] = $record->password;
468 $backpack['externalbackpackid'] = $record->id;
469 $DB->insert_record('badge_backpack', (object) $backpack);
470 }
471 }
472
3cae9421 473 $dbman->drop_field($table, $field);
931f36ce 474 }
df177126
PD
475
476 // Main savepoint reached.
477 upgrade_main_savepoint(true, 2021052500.33);
931f36ce
AN
478 }
479
d5be2887 480 if ($oldversion < 2021052500.36) {
6ff3087f
MG
481 // Define table payment_accounts to be created.
482 $table = new xmldb_table('payment_accounts');
483
484 // Adding fields to table payment_accounts.
485 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
486 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
487 $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null);
488 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
489 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
410973cf 490 $table->add_field('archived', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
6ff3087f
MG
491 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
492 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
493
494 // Adding keys to table payment_accounts.
495 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
496
497 // Conditionally launch create table for payment_accounts.
498 if (!$dbman->table_exists($table)) {
499 $dbman->create_table($table);
500 }
501
502 // Define table payment_gateways to be created.
503 $table = new xmldb_table('payment_gateways');
504
505 // Adding fields to table payment_gateways.
506 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
507 $table->add_field('accountid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
508 $table->add_field('gateway', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
509 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1');
510 $table->add_field('config', XMLDB_TYPE_TEXT, null, null, null, null, null);
511 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
512 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
513
514 // Adding keys to table payment_gateways.
515 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
516 $table->add_key('accountid', XMLDB_KEY_FOREIGN, ['accountid'], 'payment_accounts', ['id']);
517
518 // Conditionally launch create table for payment_gateways.
519 if (!$dbman->table_exists($table)) {
520 $dbman->create_table($table);
521 }
522
410973cf 523 // Define table payments to be created.
61766b3d 524 $table = new xmldb_table('payments');
61766b3d 525
410973cf
SR
526 // Adding fields to table payments.
527 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
528 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
529 $table->add_field('paymentarea', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL, null, null);
d5a9d6e5 530 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
410973cf
SR
531 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
532 $table->add_field('amount', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null);
533 $table->add_field('currency', XMLDB_TYPE_CHAR, '3', null, XMLDB_NOTNULL, null, null);
534 $table->add_field('accountid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
535 $table->add_field('gateway', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
536 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
537 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
61766b3d 538
410973cf
SR
539 // Adding keys to table payments.
540 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
541 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
542 $table->add_key('accountid', XMLDB_KEY_FOREIGN, ['accountid'], 'payment_accounts', ['id']);
61766b3d 543
410973cf
SR
544 // Adding indexes to table payments.
545 $table->add_index('gateway', XMLDB_INDEX_NOTUNIQUE, ['gateway']);
d5a9d6e5 546 $table->add_index('component-paymentarea-itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'paymentarea', 'itemid']);
61766b3d 547
410973cf
SR
548 // Conditionally launch create table for payments.
549 if (!$dbman->table_exists($table)) {
550 $dbman->create_table($table);
1c4620bc 551 }
1c4620bc
P
552
553 // Main savepoint reached.
931f36ce 554 upgrade_main_savepoint(true, 2021052500.36);
1c4620bc
P
555 }
556
8e3031ae
PD
557 if ($oldversion < 2021052500.42) {
558 // Get all lessons that are set with a completion criteria of 'requires grade' but with no grade type set.
559 $sql = "SELECT cm.id
560 FROM {course_modules} cm
561 JOIN {lesson} l ON l.id = cm.instance
562 JOIN {modules} m ON m.id = cm.module
563 WHERE m.name = :name AND cm.completiongradeitemnumber IS NOT NULL AND l.grade = :grade";
564
565 do {
566 if ($invalidconfigrations = $DB->get_records_sql($sql, ['name' => 'lesson', 'grade' => 0], 0, 1000)) {
567 list($insql, $inparams) = $DB->get_in_or_equal(array_keys($invalidconfigrations), SQL_PARAMS_NAMED);
568 $DB->set_field_select('course_modules', 'completiongradeitemnumber', null, "id $insql", $inparams);
569 }
570 } while ($invalidconfigrations);
571
572 upgrade_main_savepoint(true, 2021052500.42);
573 }
574
cd4d3879 575 if ($oldversion < 2021052500.55) {
e8bd3b41
SL
576 $DB->delete_records_select('event', "eventtype = 'category' AND categoryid = 0 AND userid <> 0");
577
cd4d3879 578 upgrade_main_savepoint(true, 2021052500.55);
e8bd3b41
SL
579 }
580
3776fbaf
FM
581 if ($oldversion < 2021052500.59) {
582 // Define field visibility to be added to contentbank_content.
583 $table = new xmldb_table('contentbank_content');
584 $field = new xmldb_field('visibility', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'contextid');
585
586 // Conditionally launch add field visibility.
587 if (!$dbman->field_exists($table, $field)) {
588 $dbman->add_field($table, $field);
589 }
590
591 // Main savepoint reached.
592 upgrade_main_savepoint(true, 2021052500.59);
593 }
594
3d117c19 595 if ($oldversion < 2021052500.60) {
3aed37ee
FM
596
597 // We are going to remove the field 'hidepicture' from the groups
598 // so we need to remove the pictures from those groups. But we prevent
599 // the execution twice because this could be executed again when upgrading
600 // to different versions.
601 if ($dbman->field_exists('groups', 'hidepicture')) {
602
603 $sql = "SELECT g.id, g.courseid, ctx.id AS contextid
604 FROM {groups} g
605 JOIN {context} ctx
606 ON ctx.instanceid = g.courseid
607 AND ctx.contextlevel = :contextlevel
608 WHERE g.hidepicture = 1";
609
610 // Selecting all the groups that have hide picture enabled, and organising them by context.
611 $groupctx = [];
612 $records = $DB->get_recordset_sql($sql, ['contextlevel' => CONTEXT_COURSE]);
613 foreach ($records as $record) {
614 if (!isset($groupctx[$record->contextid])) {
615 $groupctx[$record->contextid] = [];
616 }
617 $groupctx[$record->contextid][] = $record->id;
618 }
619 $records->close();
620
621 // Deleting the group files.
622 $fs = get_file_storage();
623 foreach ($groupctx as $contextid => $groupids) {
624 list($in, $inparams) = $DB->get_in_or_equal($groupids, SQL_PARAMS_NAMED);
625 $fs->delete_area_files_select($contextid, 'group', 'icon', $in, $inparams);
626 }
627
628 // Updating the database to remove picture from all those groups.
629 $sql = "UPDATE {groups} SET picture = :pic WHERE hidepicture = :hide";
630 $DB->execute($sql, ['pic' => 0, 'hide' => 1]);
631 }
632
633 // Define field hidepicture to be dropped from groups.
634 $table = new xmldb_table('groups');
635 $field = new xmldb_field('hidepicture');
636
637 // Conditionally launch drop field hidepicture.
638 if ($dbman->field_exists($table, $field)) {
639 $dbman->drop_field($table, $field);
640 }
641
642 // Main savepoint reached.
3d117c19 643 upgrade_main_savepoint(true, 2021052500.60);
3aed37ee
FM
644 }
645
9e5655b7
SA
646 if ($oldversion < 2021052500.64) {
647 // Get all the external backpacks and update the sortorder column, to avoid repeated/wrong values. As sortorder was not
648 // used since now, the id column will be the criteria to follow for re-ordering them with a valid value.
649 $i = 1;
650 $records = $DB->get_records('badge_external_backpack', null, 'id ASC');
651 foreach ($records as $record) {
652 $record->sortorder = $i++;
653 $DB->update_record('badge_external_backpack', $record);
654 }
655
656 upgrade_main_savepoint(true, 2021052500.64);
657 }
658
49c1d41a
SA
659 if ($oldversion < 2021052500.67) {
660 // The $CFG->badges_site_backpack setting has been removed because it's not required anymore. From now, the default backpack
661 // will be the one with lower sortorder value.
662 unset_config('badges_site_backpack');
663
664 upgrade_main_savepoint(true, 2021052500.67);
665 }
666
5066c602
SA
667 if ($oldversion < 2021052500.69) {
668
669 // Define field type to be added to oauth2_issuer.
670 $table = new xmldb_table('oauth2_issuer');
671 $field = new xmldb_field('servicetype', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'requireconfirmation');
672
673 // Conditionally launch add field type.
674 if (!$dbman->field_exists($table, $field)) {
675 $dbman->add_field($table, $field);
676 }
677
678 // Set existing values to the proper servicetype value.
679 // It's not critical if the servicetype column doesn't contain the proper value for Google, Microsoft, Facebook or
680 // Nextcloud services because, for now, this value is used for services using different discovery method.
681 // However, let's try to upgrade it using the default value for the baseurl or image. If any of these default values
682 // have been changed, the servicetype column will remain NULL.
683 $recordset = $DB->get_recordset('oauth2_issuer');
684 foreach ($recordset as $record) {
685 if ($record->baseurl == 'https://accounts.google.com/') {
686 $record->servicetype = 'google';
687 $DB->update_record('oauth2_issuer', $record);
688 } else if ($record->image == 'https://www.microsoft.com/favicon.ico') {
689 $record->servicetype = 'microsoft';
690 $DB->update_record('oauth2_issuer', $record);
691 } else if ($record->image == 'https://facebookbrand.com/wp-content/uploads/2016/05/flogo_rgb_hex-brc-site-250.png') {
692 $record->servicetype = 'facebook';
693 $DB->update_record('oauth2_issuer', $record);
694 } else if ($record->image == 'https://nextcloud.com/wp-content/themes/next/assets/img/common/favicon.png?x16328') {
695 $record->servicetype = 'nextcloud';
696 $DB->update_record('oauth2_issuer', $record);
697 }
698 }
699 $recordset->close();
700
701 // Main savepoint reached.
702 upgrade_main_savepoint(true, 2021052500.69);
703 }
704
680018c9
SL
705 if ($oldversion < 2021052500.74) {
706 // Define field 'showactivitydates' to be added to course table.
707 $table = new xmldb_table('course');
708 $field = new xmldb_field('showactivitydates', XMLDB_TYPE_INTEGER, '1', null,
709 XMLDB_NOTNULL, null, '0', 'originalcourseid');
710
711 if (!$dbman->field_exists($table, $field)) {
712 $dbman->add_field($table, $field);
713 }
714
715 // Main savepoint reached.
716 upgrade_main_savepoint(true, 2021052500.74);
717 }
718
a4f7c1d9
SL
719 if ($oldversion < 2021052500.75) {
720 // Define field 'showcompletionconditions' to be added to course.
721 $table = new xmldb_table('course');
722 $field = new xmldb_field('showcompletionconditions', XMLDB_TYPE_INTEGER, '1', null,
723 XMLDB_NOTNULL, null, '1', 'completionnotify');
724
725 if (!$dbman->field_exists($table, $field)) {
726 $dbman->add_field($table, $field);
727 }
728
729 // Main savepoint reached.
730 upgrade_main_savepoint(true, 2021052500.75);
731 }
732
d3d3b3bd
SA
733 if ($oldversion < 2021052500.78) {
734
735 // Define field enabled to be added to h5p_libraries.
736 $table = new xmldb_table('h5p_libraries');
737 $field = new xmldb_field('enabled', XMLDB_TYPE_INTEGER, '1', null, null, null, '1', 'example');
738
739 // Conditionally launch add field enabled.
740 if (!$dbman->field_exists($table, $field)) {
741 $dbman->add_field($table, $field);
742 }
743
744 // Main savepoint reached.
745 upgrade_main_savepoint(true, 2021052500.78);
746 }
747
610b339c 748 if ($oldversion < 2021052500.83) {
0152fdbd
MG
749
750 // Define field loginpagename to be added to oauth2_issuer.
751 $table = new xmldb_table('oauth2_issuer');
752 $field = new xmldb_field('loginpagename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'servicetype');
753
754 // Conditionally launch add field loginpagename.
755 if (!$dbman->field_exists($table, $field)) {
756 $dbman->add_field($table, $field);
757 }
758
759 // Main savepoint reached.
610b339c 760 upgrade_main_savepoint(true, 2021052500.83);
0152fdbd
MG
761 }
762
8a53fe7f 763 if ($oldversion < 2021052500.84) {
f9e1c258
BB
764 require_once($CFG->dirroot . '/user/profile/field/social/upgradelib.php');
765 $table = new xmldb_table('user');
766 $tablecolumns = ['icq', 'skype', 'aim', 'yahoo', 'msn', 'url'];
767
768 foreach ($tablecolumns as $column) {
769 $field = new xmldb_field($column);
770 if ($dbman->field_exists($table, $field)) {
771 user_profile_social_moveto_profilefield($column);
772 $dbman->drop_field($table, $field);
773 }
774 }
775
776 // Update all module availability if it relies on the old user fields.
777 user_profile_social_update_module_availability();
778
779 // Remove field mapping for oauth2.
780 $DB->delete_records('oauth2_user_field_mapping', array('internalfield' => 'url'));
781
782 // Main savepoint reached.
8a53fe7f 783 upgrade_main_savepoint(true, 2021052500.84);
f9e1c258
BB
784 }
785
5b028284
SL
786 if ($oldversion < 2021052500.85) {
787 require_once($CFG->libdir . '/db/upgradelib.php');
788
789 // Check if this site has executed the problematic upgrade steps.
790 $needsfixing = upgrade_calendar_site_status(false);
791
792 // Only queue the task if this site has been affected by the problematic upgrade step.
793 if ($needsfixing) {
794
795 // Create adhoc task to search and recover orphaned calendar events.
796 $record = new \stdClass();
797 $record->classname = '\core\task\calendar_fix_orphaned_events';
798
799 // Next run time based from nextruntime computation in \core\task\manager::queue_adhoc_task().
800 $nextruntime = time() - 1;
801 $record->nextruntime = $nextruntime;
802 $DB->insert_record('task_adhoc', $record);
803 }
804
805 // Main savepoint reached.
806 upgrade_main_savepoint(true, 2021052500.85);
807 }
808
fca42002
JP
809 if ($oldversion < 2021052500.87) {
810 // Changing the default of field showcompletionconditions on table course to 0.
811 $table = new xmldb_table('course');
812 $field = new xmldb_field('showcompletionconditions', XMLDB_TYPE_INTEGER, '1', null, null, null, null, 'showactivitydates');
813
814 // Launch change of nullability for field showcompletionconditions.
815 $dbman->change_field_notnull($table, $field);
816
817 // Launch change of default for field showcompletionconditions.
818 $dbman->change_field_default($table, $field);
819
820 // Set showcompletionconditions to null for courses which don't track completion.
821 $sql = "UPDATE {course}
822 SET showcompletionconditions = null
823 WHERE enablecompletion <> 1";
824 $DB->execute($sql);
825
826 // Main savepoint reached.
827 upgrade_main_savepoint(true, 2021052500.87);
828 }
829
430746d3
IT
830 if ($oldversion < 2021052500.90) {
831 // Remove usemodchooser user preference for every user.
832 $DB->delete_records('user_preferences', ['name' => 'usemodchooser']);
833
834 // Main savepoint reached.
835 upgrade_main_savepoint(true, 2021052500.90);
836 }
837
0f5e9aa7 838 if ($oldversion < 2021060200.00) {
ee3c6ad3
MG
839
840 // Define index name (not unique) to be added to user_preferences.
841 $table = new xmldb_table('user_preferences');
842 $index = new xmldb_index('name', XMLDB_INDEX_NOTUNIQUE, ['name']);
843
844 // Conditionally launch add index name.
845 if (!$dbman->index_exists($table, $index)) {
846 $dbman->add_index($table, $index);
847 }
848
849 // Main savepoint reached.
0f5e9aa7 850 upgrade_main_savepoint(true, 2021060200.00);
ee3c6ad3
MG
851 }
852
7782eeb5 853 if ($oldversion < 2021060900.00) {
8e71f6b1
PD
854 // Update the externalfield to be larger.
855 $table = new xmldb_table('oauth2_user_field_mapping');
856 $field = new xmldb_field('externalfield', XMLDB_TYPE_CHAR, '500', null, XMLDB_NOTNULL, false, null, 'issuerid');
857 $dbman->change_field_type($table, $field);
858
859 // Main savepoint reached.
7782eeb5 860 upgrade_main_savepoint(true, 2021060900.00);
8e71f6b1
PD
861 }
862
542f2927
PH
863 if ($oldversion < 2021072800.01) {
864 // Define table reportbuilder_report to be created.
865 $table = new xmldb_table('reportbuilder_report');
866
867 // Adding fields to table reportbuilder_report.
868 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
869 $table->add_field('source', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
870 $table->add_field('type', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0');
871 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
872 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
873 $table->add_field('area', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
874 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
875 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
876 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
877 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
878 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
879
880 // Adding keys to table reportbuilder_report.
881 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
882 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']);
883 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']);
884 $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']);
885
886 // Conditionally launch create table for reportbuilder_report.
887 if (!$dbman->table_exists($table)) {
888 $dbman->create_table($table);
889 }
890
891 // Main savepoint reached.
892 upgrade_main_savepoint(true, 2021072800.01);
893 }
894
c6d11f0f
SA
895 if ($oldversion < 2021090200.01) {
896 // Remove qformat_webct (unless it has manually been added back).
897 if (!file_exists($CFG->dirroot . '/question/format/webct/format.php')) {
898 unset_all_config_for_plugin('qformat_webct');
899 }
900
901 // Main savepoint reached.
902 upgrade_main_savepoint(true, 2021090200.01);
903 }
904
f471a7d2
SA
905 if ($oldversion < 2021091100.01) {
906 // If message_jabber is no longer present, remove it.
907 if (!file_exists($CFG->dirroot . '/message/output/jabber/message_output_jabber.php')) {
908 // Remove Jabber from the notification plugins list.
909 $DB->delete_records('message_processors', ['name' => 'jabber']);
910
911 // Remove user preference settings.
912 $DB->delete_records('user_preferences', ['name' => 'message_processor_jabber_jabberid']);
913 $sql = 'SELECT *
914 FROM {user_preferences} up
915 WHERE ' . $DB->sql_like('up.name', ':name', false, false) . ' AND ' .
916 $DB->sql_like('up.value', ':value', false, false);
917 $params = [
918 'name' => 'message_provider_%',
919 'value' => '%jabber%',
920 ];
921 $jabbersettings = $DB->get_recordset_sql($sql, $params);
922 foreach ($jabbersettings as $jabbersetting) {
923 // Remove 'jabber' from the value.
924 $jabbersetting->value = implode(',', array_diff(explode(',', $jabbersetting->value), ['jabber']));
925 $DB->update_record('user_preferences', $jabbersetting);
926 }
927 $jabbersettings->close();
928
929 // Clean config settings.
930 unset_config('jabberhost');
931 unset_config('jabberserver');
932 unset_config('jabberusername');
933 unset_config('jabberpassword');
934 unset_config('jabberport');
935
936 // Remove default notification preferences.
937 $like = $DB->sql_like('name', '?', true, true, false, '|');
938 $params = [$DB->sql_like_escape('jabber_provider_', '|') . '%'];
939 $DB->delete_records_select('config_plugins', $like, $params);
940
941 // Clean config config settings.
942 unset_all_config_for_plugin('message_jabber');
943 }
944
945 upgrade_main_savepoint(true, 2021091100.01);
946 }
947
2d65b1eb 948 if ($oldversion < 2021091100.02) {
3f2f2e85
SA
949 // Set the description field to HTML format for the Default course category.
950 $category = $DB->get_record('course_categories', ['id' => 1]);
951
dd540652 952 if (!empty($category) && $category->descriptionformat == FORMAT_MOODLE) {
3f2f2e85
SA
953 // Format should be changed only if it's still set to FORMAT_MOODLE.
954 if (!is_null($category->description)) {
955 // If description is not empty, format the content to HTML.
956 $category->description = format_text($category->description, FORMAT_MOODLE);
957 }
958 $category->descriptionformat = FORMAT_HTML;
959 $DB->update_record('course_categories', $category);
960 }
961
962 // Main savepoint reached.
2d65b1eb 963 upgrade_main_savepoint(true, 2021091100.02);
3f2f2e85
SA
964 }
965
7958fa72
AA
966 if ($oldversion < 2021091700.01) {
967 // Default 'off' for existing sites as this is the behaviour they had earlier.
968 set_config('enroladminnewcourse', false);
969
970 // Main savepoint reached.
971 upgrade_main_savepoint(true, 2021091700.01);
972 }
973
e6e32acd 974 if ($oldversion < 2021091700.02) {
ba06999e
SA
975 // If portfolio_picasa is no longer present, remove it.
976 if (!file_exists($CFG->dirroot . '/portfolio/picasa/version.php')) {
977 $instance = $DB->get_record('portfolio_instance', ['plugin' => 'picasa']);
978 if (!empty($instance)) {
979 // Remove all records from portfolio_instance_config.
980 $DB->delete_records('portfolio_instance_config', ['instance' => $instance->id]);
981 // Remove all records from portfolio_instance_user.
982 $DB->delete_records('portfolio_instance_user', ['instance' => $instance->id]);
983 // Remove all records from portfolio_log.
984 $DB->delete_records('portfolio_log', ['portfolio' => $instance->id]);
985 // Remove all records from portfolio_tempdata.
986 $DB->delete_records('portfolio_tempdata', ['instance' => $instance->id]);
987 // Remove the record from the portfolio_instance table.
988 $DB->delete_records('portfolio_instance', ['id' => $instance->id]);
989 }
990
991 // Clean config.
992 unset_all_config_for_plugin('portfolio_picasa');
993 }
994
e6e32acd 995 upgrade_main_savepoint(true, 2021091700.02);
ba06999e
SA
996 }
997
e6e32acd 998 if ($oldversion < 2021091700.03) {
128ebcc4
SA
999 // If repository_picasa is no longer present, remove it.
1000 if (!file_exists($CFG->dirroot . '/repository/picasa/version.php')) {
1001 $instance = $DB->get_record('repository', ['type' => 'picasa']);
1002 if (!empty($instance)) {
1003 // Remove all records from repository_instance_config table.
1004 $DB->delete_records('repository_instance_config', ['instanceid' => $instance->id]);
1005 // Remove all records from repository_instances table.
1006 $DB->delete_records('repository_instances', ['typeid' => $instance->id]);
1007 // Remove the record from the repository table.
1008 $DB->delete_records('repository', ['id' => $instance->id]);
1009 }
1010
1011 // Clean config.
1012 unset_all_config_for_plugin('picasa');
1013
1014 // Remove orphaned files.
1015 upgrade_delete_orphaned_file_records();
1016 }
1017
e6e32acd 1018 upgrade_main_savepoint(true, 2021091700.03);
128ebcc4
SA
1019 }
1020
0e979b85 1021 if ($oldversion < 2021091700.04) {
a0d3e32a
SA
1022 // Remove media_swf (unless it has manually been added back).
1023 if (!file_exists($CFG->dirroot . '/media/player/swf/classes/plugin.php')) {
1024 unset_all_config_for_plugin('media_swf');
1025 }
1026
0e979b85 1027 upgrade_main_savepoint(true, 2021091700.04);
a0d3e32a
SA
1028 }
1029
bad5b1d8 1030 if ($oldversion < 2021092400.01) {
1031 // If tool_health is no longer present, remove it.
1032 if (!file_exists($CFG->dirroot . '/admin/tool/health/version.php')) {
1033 // Clean config.
1034 unset_all_config_for_plugin('tool_health');
1035 }
1036
1037 // Main savepoint reached.
1038 upgrade_main_savepoint(true, 2021092400.01);
1039 }
1040
44f06edd 1041 if ($oldversion < 2021092400.03) {
ffa9b692
PH
1042 // Remove repository_picasa configuration (unless it has manually been added back).
1043 if (!file_exists($CFG->dirroot . '/repository/picasa/version.php')) {
1044 unset_all_config_for_plugin('repository_picasa');
1045 }
1046
44f06edd 1047 upgrade_main_savepoint(true, 2021092400.03);
ffa9b692
PH
1048 }
1049
70e6deac
SA
1050 if ($oldversion < 2021100300.01) {
1051 // Remove repository_skydrive (unless it has manually been added back).
1052 if (!file_exists($CFG->dirroot . '/repository/skydrive/lib.php')) {
1053 unset_all_config_for_plugin('repository_skydrive');
1054 }
1055
1056 // Main savepoint reached.
1057 upgrade_main_savepoint(true, 2021100300.01);
1058 }
1059
3482a549 1060 if ($oldversion < 2021100300.02) {
32576936
SA
1061 // Remove filter_censor (unless it has manually been added back).
1062 if (!file_exists($CFG->dirroot . '/filter/censor/filter.php')) {
1063 unset_all_config_for_plugin('filter_censor');
1064 }
1065
1066 // Main savepoint reached.
3482a549 1067 upgrade_main_savepoint(true, 2021100300.02);
32576936
SA
1068 }
1069
678826ef 1070 if ($oldversion < 2021100600.01) {
1071 // Remove qformat_examview (unless it has manually been added back).
1072 if (!file_exists($CFG->dirroot . '/question/format/examview/format.php')) {
1073 unset_all_config_for_plugin('qformat_examview');
1074 }
1075
1076 // Main savepoint reached.
1077 upgrade_main_savepoint(true, 2021100600.01);
1078 }
1079
b4675942 1080 if ($oldversion < 2021100600.02) {
66313774
P
1081 $table = new xmldb_table('course_completion_defaults');
1082
1083 // Adding fields to table course_completion_defaults.
1084 $field = new xmldb_field('completionpassgrade', XMLDB_TYPE_INTEGER, '1', null,
1085 XMLDB_NOTNULL, null, '0', 'completionusegrade');
1086
1087 // Conditionally launch add field for course_completion_defaults.
1088 if (!$dbman->field_exists($table, $field)) {
1089 $dbman->add_field($table, $field);
1090 }
1091
b4675942 1092 upgrade_main_savepoint(true, 2021100600.02);
66313774
P
1093 }
1094
b4675942 1095 if ($oldversion < 2021100600.03) {
90acd8d3
P
1096 $table = new xmldb_table('course_modules');
1097
1098 // Adding new fields to table course_module table.
1099 $field = new xmldb_field('completionpassgrade', XMLDB_TYPE_INTEGER, '1', null,
1100 XMLDB_NOTNULL, null, '0', 'completionexpected');
1101 // Conditionally launch create table for course_completion_defaults.
1102 if (!$dbman->field_exists($table, $field)) {
1103 $dbman->add_field($table, $field);
1104 }
1105
b4675942 1106 upgrade_main_savepoint(true, 2021100600.03);
90acd8d3
P
1107 }
1108
da8b6582 1109 if ($oldversion < 2021100600.04) {
5ea613c9
AR
1110 // Define index itemtype-mod-inst-course (not unique) to be added to grade_items.
1111 $table = new xmldb_table('grade_items');
1112 $index = new xmldb_index('itemtype-mod-inst-course', XMLDB_INDEX_NOTUNIQUE,
1113 ['itemtype', 'itemmodule', 'iteminstance', 'courseid']);
1114
1115 // Conditionally launch add index itemtype-mod-inst-course.
1116 if (!$dbman->index_exists($table, $index)) {
1117 $dbman->add_index($table, $index);
1118 }
1119
1120 // Main savepoint reached.
da8b6582 1121 upgrade_main_savepoint(true, 2021100600.04);
5ea613c9
AR
1122 }
1123
95967d62
PH
1124 if ($oldversion < 2021101900.01) {
1125 $table = new xmldb_table('reportbuilder_report');
1126
1127 // Define field name to be added to reportbuilder_report.
1128 $field = new xmldb_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'id');
1129 if (!$dbman->field_exists($table, $field)) {
1130 $dbman->add_field($table, $field);
1131 }
1132
1133 // Define field conditiondata to be added to reportbuilder_report.
1134 $field = new xmldb_field('conditiondata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'type');
1135 if (!$dbman->field_exists($table, $field)) {
1136 $dbman->add_field($table, $field);
1137 }
1138
1139 // Define table reportbuilder_column to be created.
1140 $table = new xmldb_table('reportbuilder_column');
1141
1142 // Adding fields to table reportbuilder_column.
1143 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1144 $table->add_field('reportid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1145 $table->add_field('uniqueidentifier', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1146 $table->add_field('aggregation', XMLDB_TYPE_CHAR, '32', null, null, null, null);
1147 $table->add_field('heading', XMLDB_TYPE_CHAR, '255', null, null, null, null);
1148 $table->add_field('columnorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1149 $table->add_field('sortenabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
1150 $table->add_field('sortdirection', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null);
1151 $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
1152 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1153 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1154 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1155 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1156
1157 // Adding keys to table reportbuilder_column.
1158 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1159 $table->add_key('reportid', XMLDB_KEY_FOREIGN, ['reportid'], 'reportbuilder_report', ['id']);
1160 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']);
1161 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']);
1162
1163 // Conditionally launch create table for reportbuilder_column.
1164 if (!$dbman->table_exists($table)) {
1165 $dbman->create_table($table);
1166 }
1167
1168 // Define table reportbuilder_filter to be created.
1169 $table = new xmldb_table('reportbuilder_filter');
1170
1171 // Adding fields to table reportbuilder_filter.
1172 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1173 $table->add_field('reportid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1174 $table->add_field('uniqueidentifier', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1175 $table->add_field('heading', XMLDB_TYPE_CHAR, '255', null, null, null, null);
1176 $table->add_field('iscondition', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
1177 $table->add_field('filterorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1178 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1179 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1180 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1181 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1182
1183 // Adding keys to table reportbuilder_filter.
1184 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1185 $table->add_key('reportid', XMLDB_KEY_FOREIGN, ['reportid'], 'reportbuilder_report', ['id']);
1186 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']);
1187 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']);
1188
1189 // Conditionally launch create table for reportbuilder_filter.
1190 if (!$dbman->table_exists($table)) {
1191 $dbman->create_table($table);
1192 }
1193
1194 // Main savepoint reached.
1195 upgrade_main_savepoint(true, 2021101900.01);
1196 }
1197
3c6ad8ac 1198 if ($oldversion < 2021102600.01) {
1199 // Remove block_quiz_results (unless it has manually been added back).
1200 if (!file_exists($CFG->dirroot . '/blocks/quiz_result/block_quiz_results.php')) {
1201 // Delete instances.
1202 $instances = $DB->get_records_list('block_instances', 'blockname', ['quiz_results']);
1203 $instanceids = array_keys($instances);
1204
1205 if (!empty($instanceids)) {
1206 blocks_delete_instances($instanceids);
1207 }
1208
1209 // Delete the block from the block table.
1210 $DB->delete_records('block', array('name' => 'quiz_results'));
1211
1212 // Remove capabilities.
1213 capabilities_cleanup('block_quiz_results');
1214 // Clean config.
1215 unset_all_config_for_plugin('block_quiz_results');
1216
1217 // Remove Moodle-level quiz_results based capabilities.
1218 $capabilitiestoberemoved = ['block/quiz_results:addinstance'];
1219 // Delete any role_capabilities for the old roles.
1220 $DB->delete_records_list('role_capabilities', 'capability', $capabilitiestoberemoved);
1221 // Delete the capability itself.
1222 $DB->delete_records_list('capabilities', 'name', $capabilitiestoberemoved);
1223 }
1224
1225 upgrade_main_savepoint(true, 2021102600.01);
1226 }
1227
d2d9d608 1228 if ($oldversion < 2021102900.02) {
0a5d3873 1229 // If portfolio_boxnet is no longer present, remove it.
1230 if (!file_exists($CFG->dirroot . '/portfolio/boxnet/version.php')) {
1231 $instance = $DB->get_record('portfolio_instance', ['plugin' => 'boxnet']);
1232 if (!empty($instance)) {
1233 // Remove all records from portfolio_instance_config.
1234 $DB->delete_records('portfolio_instance_config', ['instance' => $instance->id]);
1235 // Remove all records from portfolio_instance_user.
1236 $DB->delete_records('portfolio_instance_user', ['instance' => $instance->id]);
1237 // Remove all records from portfolio_log.
1238 $DB->delete_records('portfolio_log', ['portfolio' => $instance->id]);
1239 // Remove all records from portfolio_tempdata.
1240 $DB->delete_records('portfolio_tempdata', ['instance' => $instance->id]);
1241 // Remove the record from the portfolio_instance table.
1242 $DB->delete_records('portfolio_instance', ['id' => $instance->id]);
1243 }
1244
1245 // Clean config.
1246 unset_all_config_for_plugin('portfolio_boxnet');
1247 }
1248
1249 // If repository_boxnet is no longer present, remove it.
1250 if (!file_exists($CFG->dirroot . '/repository/boxnet/version.php')) {
1251 $instance = $DB->get_record('repository', ['type' => 'boxnet']);
1252 if (!empty($instance)) {
1253 // Remove all records from repository_instance_config table.
1254 $DB->delete_records('repository_instance_config', ['instanceid' => $instance->id]);
1255 // Remove all records from repository_instances table.
1256 $DB->delete_records('repository_instances', ['typeid' => $instance->id]);
1257 // Remove the record from the repository table.
1258 $DB->delete_records('repository', ['id' => $instance->id]);
1259 }
1260
1261 // Clean config.
1262 unset_all_config_for_plugin('repository_boxnet');
1263
d2d9d608
AN
1264 // The boxnet repository plugin stores some config in 'boxnet' incorrectly.
1265 unset_all_config_for_plugin('boxnet');
1266
0a5d3873 1267 // Remove orphaned files.
1268 upgrade_delete_orphaned_file_records();
1269 }
1270
d2d9d608 1271 upgrade_main_savepoint(true, 2021102900.02);
0a5d3873 1272 }
1273
6f7defee 1274 if ($oldversion < 2021110100.00) {
b2dd94ab
DM
1275
1276 // Define table reportbuilder_audience to be created.
1277 $table = new xmldb_table('reportbuilder_audience');
1278
1279 // Adding fields to table reportbuilder_audience.
1280 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1281 $table->add_field('reportid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1282 $table->add_field('classname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1283 $table->add_field('configdata', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
1284 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1285 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1286 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1287 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1288
1289 // Adding keys to table reportbuilder_audience.
1290 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1291 $table->add_key('reportid', XMLDB_KEY_FOREIGN, ['reportid'], 'reportbuilder_report', ['id']);
1292 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']);
1293 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']);
1294
1295 // Conditionally launch create table for reportbuilder_audience.
1296 if (!$dbman->table_exists($table)) {
1297 $dbman->create_table($table);
1298 }
1299
1300 // Main savepoint reached.
6f7defee 1301 upgrade_main_savepoint(true, 2021110100.00);
b2dd94ab
DM
1302 }
1303
2ab697f6 1304 if ($oldversion < 2021110800.02) {
89e59a60
SL
1305 // Define a field 'downloadcontent' in the 'course_modules' table.
1306 $table = new xmldb_table('course_modules');
1307 $field = new xmldb_field('downloadcontent', XMLDB_TYPE_INTEGER, '1', null, null, null, 1, 'deletioninprogress');
1308
1309 // Conditionally launch add field 'downloadcontent'.
1310 if (!$dbman->field_exists($table, $field)) {
1311 $dbman->add_field($table, $field);
1312 }
1313
1314 // Main savepoint reached.
2ab697f6 1315 upgrade_main_savepoint(true, 2021110800.02);
89e59a60
SL
1316 }
1317
aaa7a5a4
MM
1318 if ($oldversion < 2021110800.03) {
1319
1320 // Define field settingsdata to be added to reportbuilder_report.
1321 $table = new xmldb_table('reportbuilder_report');
1322 $field = new xmldb_field('settingsdata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'conditiondata');
1323
1324 // Conditionally launch add field settingsdata.
1325 if (!$dbman->field_exists($table, $field)) {
1326 $dbman->add_field($table, $field);
1327 }
1328
1329 // Main savepoint reached.
1330 upgrade_main_savepoint(true, 2021110800.03);
1331 }
1332
738d4cac 1333 if ($oldversion < 2021111700.00) {
6ca9c215
MM
1334 $mycoursespage = new stdClass();
1335 $mycoursespage->userid = null;
1336 $mycoursespage->name = '__courses';
1337 $mycoursespage->private = 0;
1338 $mycoursespage->sortorder = 0;
1339 $DB->insert_record('my_pages', $mycoursespage);
1340
738d4cac 1341 upgrade_main_savepoint(true, 2021111700.00);
6ca9c215
MM
1342 }
1343
357ddcaf 1344 if ($oldversion < 2021111700.01) {
be11216d
PH
1345
1346 // Define field uniquerows to be added to reportbuilder_report.
1347 $table = new xmldb_table('reportbuilder_report');
1348 $field = new xmldb_field('uniquerows', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'type');
1349
1350 // Conditionally launch add field uniquerows.
1351 if (!$dbman->field_exists($table, $field)) {
1352 $dbman->add_field($table, $field);
1353 }
1354
1355 // Main savepoint reached.
357ddcaf 1356 upgrade_main_savepoint(true, 2021111700.01);
be11216d
PH
1357 }
1358
40818b52 1359 if ($oldversion < 2021120100.01) {
7de559fa
HN
1360
1361 // Get current configuration data.
1362 $currentcustomusermenuitems = str_replace(["\r\n", "\r"], "\n", $CFG->customusermenuitems);
1363 $lines = explode("\n", $currentcustomusermenuitems);
1364 $lines = array_map('trim', $lines);
1365 $calendarcustomusermenu = 'calendar,core_calendar|/calendar/view.php?view=month|i/calendar';
1366
1367 if (!in_array($calendarcustomusermenu, $lines)) {
1368 // Add Calendar item to the menu.
1369 array_splice($lines, 1, 0, [$calendarcustomusermenu]);
1370 set_config('customusermenuitems', implode("\n", $lines));
1371 }
1372
1373 // Main savepoint reached.
40818b52 1374 upgrade_main_savepoint(true, 2021120100.01);
7de559fa
HN
1375 }
1376
de534129
MG
1377 if ($oldversion < 2021121400.01) {
1378 // The $CFG->grade_navmethod setting has been removed because it's not required anymore. This setting was used
1379 // to set the type of navigation (tabs or dropdown box) which will be displayed in gradebook. However, these
1380 // navigation methods are no longer used and replaced with tertiary navigation.
1381 unset_config('grade_navmethod');
1382
1383 // Main savepoint reached.
1384 upgrade_main_savepoint(true, 2021121400.01);
1385 }
1386
eadf1570
SL
1387 if ($oldversion < 2021121700.01) {
1388 // Get current support email setting value.
1389 $config = get_config('moodle', 'supportemail');
1390
1391 // Check if support email setting is empty and then set it to null.
1392 // We must do that so the setting is displayed during the upgrade.
1393 if (empty($config)) {
1394 set_config('supportemail', null);
1395 }
1396
1397 // Main savepoint reached.
1398 upgrade_main_savepoint(true, 2021121700.01);
1399 }
1400
e9bd499f 1401 if ($oldversion < 2021122100.00) {
8c336899
HN
1402 // Get current configuration data.
1403 $currentcustomusermenuitems = str_replace(["\r\n", "\r"], "\n", $CFG->customusermenuitems);
1404
1405 // The old default customusermenuitems config for 3.11 and below.
1406 $oldcustomusermenuitems = 'grades,grades|/grade/report/mygrades.php|t/grades
1407calendar,core_calendar|/calendar/view.php?view=month|i/calendar
1408messages,message|/message/index.php|t/message
1409preferences,moodle|/user/preferences.php|t/preferences';
1410
1411 // Check if the current customusermenuitems config matches the old customusermenuitems config.
1412 $samecustomusermenuitems = $currentcustomusermenuitems == $oldcustomusermenuitems;
1413 if ($samecustomusermenuitems) {
1414 // If the site is still using the old defaults, upgrade to the new default.
1415 $newcustomusermenuitems = 'profile,moodle|/user/profile.php
1416grades,grades|/grade/report/mygrades.php
1417calendar,core_calendar|/calendar/view.php?view=month
1418privatefiles,moodle|/user/files.php';
1419 // Set the new configuration back.
1420 set_config('customusermenuitems', $newcustomusermenuitems);
1421 } else {
1422 // If the site is not using the old defaults, only add necessary entries.
e1fefe2e
PH
1423 $lines = preg_split('/\n/', $currentcustomusermenuitems, -1, PREG_SPLIT_NO_EMPTY);
1424 $lines = array_map(static function(string $line): string {
1425 // Previous format was "<langstring>|<url>[|<pixicon>]" - pix icon is no longer supported.
1426 $lineparts = explode('|', trim($line), 3);
1427 // Return first two parts of line.
1428 return implode('|', array_slice($lineparts, 0, 2));
1429 }, $lines);
8c336899
HN
1430
1431 // Remove the Preference entry from the menu to prevent duplication
1432 // since it will be added again in user_get_user_navigation_info().
1433 $lines = array_filter($lines, function($value) {
1434 return strpos($value, 'preferences,moodle|/user/preferences.php') === false;
1435 });
1436
1437 $matches = preg_grep('/\|\/user\/files.php/i', $lines);
1438 if (!$matches) {
1439 // Add the Private files entry to the menu.
1440 $lines[] = 'privatefiles,moodle|/user/files.php';
1441 }
1442
1443 $matches = preg_grep('/\|\/user\/profile.php/i', $lines);
1444 if (!$matches) {
1445 // Add the Profile entry to top of the menu.
1446 array_unshift($lines, 'profile,moodle|/user/profile.php');
1447 }
1448
1449 // Set the new configuration back.
1450 set_config('customusermenuitems', implode("\n", $lines));
1451 }
1452
1453 // Main savepoint reached.
e9bd499f 1454 upgrade_main_savepoint(true, 2021122100.00);
8c336899
HN
1455 }
1456
445ba4f6
SA
1457
1458 if ($oldversion < 2021122100.01) {
eb460d93
PH
1459
1460 // Define field heading to be added to reportbuilder_audience.
1461 $table = new xmldb_table('reportbuilder_audience');
1462 $field = new xmldb_field('heading', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'reportid');
1463
1464 // Conditionally launch add field heading.
1465 if (!$dbman->field_exists($table, $field)) {
1466 $dbman->add_field($table, $field);
1467 }
1468
1469 // Main savepoint reached.
445ba4f6 1470 upgrade_main_savepoint(true, 2021122100.01);
eb460d93
PH
1471 }
1472
445ba4f6 1473 if ($oldversion < 2021122100.02) {
eb460d93
PH
1474
1475 // Define table reportbuilder_schedule to be created.
1476 $table = new xmldb_table('reportbuilder_schedule');
1477
1478 // Adding fields to table reportbuilder_schedule.
1479 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1480 $table->add_field('reportid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1481 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1482 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1');
1483 $table->add_field('audiences', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
1484 $table->add_field('format', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1485 $table->add_field('subject', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1486 $table->add_field('message', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
3b736bc5 1487 $table->add_field('messageformat', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
eb460d93
PH
1488 $table->add_field('userviewas', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1489 $table->add_field('timescheduled', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1490 $table->add_field('recurrence', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1491 $table->add_field('reportempty', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1492 $table->add_field('timelastsent', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1493 $table->add_field('timenextsend', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1494 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1495 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1496 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1497 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1498
1499 // Adding keys to table reportbuilder_schedule.
1500 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1501 $table->add_key('reportid', XMLDB_KEY_FOREIGN, ['reportid'], 'reportbuilder_report', ['id']);
1502 $table->add_key('userviewas', XMLDB_KEY_FOREIGN, ['userviewas'], 'user', ['id']);
1503 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']);
1504 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']);
1505
1506 // Conditionally launch create table for reportbuilder_schedule.
1507 if (!$dbman->table_exists($table)) {
1508 $dbman->create_table($table);
1509 }
1510
1511 // Main savepoint reached.
445ba4f6 1512 upgrade_main_savepoint(true, 2021122100.02);
eb460d93
PH
1513 }
1514
727f0d4d
SA
1515 if ($oldversion < 2021123000.01) {
1516 // The tool_admin_presets tables have been moved to core, because core_adminpresets component has been created, so
1517 // it can interact with the rest of core.
1518 // So the tool_admin_presetsXXX tables will be renamed to adminipresetsXXX if they exists; otherwise, they will be created.
1519
1520 $tooltable = new xmldb_table('tool_admin_presets');
1521 $table = new xmldb_table('adminpresets');
1522 if ($dbman->table_exists($tooltable)) {
1523 $dbman->rename_table($tooltable, 'adminpresets');
1524 } else if (!$dbman->table_exists($table)) {
1525 // Adding fields to table adminpresets.
1526 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1527 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1528 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1529 $table->add_field('comments', XMLDB_TYPE_TEXT, null, null, null, null, null);
1530 $table->add_field('site', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1531 $table->add_field('author', XMLDB_TYPE_CHAR, '255', null, null, null, null);
1532 $table->add_field('moodleversion', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null);
1533 $table->add_field('moodlerelease', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
1534 $table->add_field('iscore', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0');
1535 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1536 $table->add_field('timeimported', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0');
1537
1538 // Adding keys to table adminpresets.
1539 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1540
1541 // Launch create table for adminpresets.
1542 $dbman->create_table($table);
1543 }
1544
1545 $tooltable = new xmldb_table('tool_admin_presets_it');
1546 $table = new xmldb_table('adminpresets_it');
1547 if ($dbman->table_exists($tooltable)) {
1548 $dbman->rename_table($tooltable, 'adminpresets_it');
1549 } else if (!$dbman->table_exists($table)) {
1550 // Adding fields to table adminpresets_it.
1551 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1552 $table->add_field('adminpresetid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1553 $table->add_field('plugin', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1554 $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
1555 $table->add_field('value', XMLDB_TYPE_TEXT, null, null, null, null, null);
1556
1557 // Adding keys to table adminpresets_it.
1558 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1559
1560 // Adding indexes to table adminpresets_it.
1561 $table->add_index('adminpresetid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetid']);
1562
1563 // Launch create table for adminpresets_it.
1564 $dbman->create_table($table);
1565 }
1566
1567 $tooltable = new xmldb_table('tool_admin_presets_it_a');
1568 $table = new xmldb_table('adminpresets_it_a');
1569 if ($dbman->table_exists($tooltable)) {
1570 $dbman->rename_table($tooltable, 'adminpresets_it_a');
1571 } else if (!$dbman->table_exists($table)) {
1572 // Adding fields to table adminpresets_it_a.
1573 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1574 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1575 $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
1576 $table->add_field('value', XMLDB_TYPE_TEXT, null, null, null, null, null);
1577
1578 // Adding keys to table adminpresets_it_a.
1579 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1580
1581 // Adding indexes to table adminpresets_it_a.
1582 $table->add_index('itemid', XMLDB_INDEX_NOTUNIQUE, ['itemid']);
1583
1584 // Launch create table for adminpresets_it_a.
1585 $dbman->create_table($table);
1586 }
1587
1588 $tooltable = new xmldb_table('tool_admin_presets_app');
1589 $table = new xmldb_table('adminpresets_app');
1590 if ($dbman->table_exists($tooltable)) {
1591 $dbman->rename_table($tooltable, 'adminpresets_app');
1592 } else if (!$dbman->table_exists($table)) {
1593 // Adding fields to table adminpresets_app.
1594 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1595 $table->add_field('adminpresetid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1596 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1597 $table->add_field('time', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1598
1599 // Adding keys to table adminpresets_app.
1600 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1601
1602 // Adding indexes to table adminpresets_app.
1603 $table->add_index('adminpresetid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetid']);
1604
1605 // Launch create table for adminpresets_app.
1606 $dbman->create_table($table);
1607 }
1608
1609 $tooltable = new xmldb_table('tool_admin_presets_app_it');
1610 $table = new xmldb_table('adminpresets_app_it');
1611 if ($dbman->table_exists($tooltable)) {
1612 $dbman->rename_table($tooltable, 'adminpresets_app_it');
1613 } else if (!$dbman->table_exists($table)) {
1614 // Adding fields to table adminpresets_app_it.
1615 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1616 $table->add_field('adminpresetapplyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1617 $table->add_field('configlogid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1618
1619 // Adding keys to table adminpresets_app_it.
1620 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1621
1622 // Adding indexes to table adminpresets_app_it.
1623 $table->add_index('configlogid', XMLDB_INDEX_NOTUNIQUE, ['configlogid']);
1624 $table->add_index('adminpresetapplyid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetapplyid']);
1625
1626 // Launch create table for adminpresets_app_it.
1627 $dbman->create_table($table);
1628 }
1629
1630 $tooltable = new xmldb_table('tool_admin_presets_app_it_a');
1631 $table = new xmldb_table('adminpresets_app_it_a');
1632 if ($dbman->table_exists($tooltable)) {
1633 $dbman->rename_table($tooltable, 'adminpresets_app_it_a');
1634 } else if (!$dbman->table_exists($table)) {
1635 // Adding fields to table adminpresets_app_it_a.
1636 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1637 $table->add_field('adminpresetapplyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1638 $table->add_field('configlogid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1639 $table->add_field('itemname', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1640
1641 // Adding keys to table adminpresets_app_it_a.
1642 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1643
1644 // Adding indexes to table adminpresets_app_it_a.
1645 $table->add_index('configlogid', XMLDB_INDEX_NOTUNIQUE, ['configlogid']);
1646 $table->add_index('adminpresetapplyid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetapplyid']);
1647
1648 // Launch create table for adminpresets_app_it_a.
1649 $dbman->create_table($table);
1650 }
1651
1652 $tooltable = new xmldb_table('tool_admin_presets_plug');
1653 $table = new xmldb_table('adminpresets_plug');
1654 if ($dbman->table_exists($tooltable)) {
1655 $dbman->rename_table($tooltable, 'adminpresets_plug');
1656 } else if (!$dbman->table_exists($table)) {
1657 // Adding fields to table adminpresets_plug.
1658 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1659 $table->add_field('adminpresetid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1660 $table->add_field('plugin', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1661 $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
1662 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0');
1663
1664 // Adding keys to table adminpresets_plug.
1665 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1666
1667 // Adding indexes to table adminpresets_plug.
1668 $table->add_index('adminpresetid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetid']);
1669
1670 // Launch create table for adminpresets_plug.
1671 $dbman->create_table($table);
1672 }
1673
1674 $tooltable = new xmldb_table('tool_admin_presets_app_plug');
1675 $table = new xmldb_table('adminpresets_app_plug');
1676 if ($dbman->table_exists($tooltable)) {
1677 $dbman->rename_table($tooltable, 'adminpresets_app_plug');
1678 } else if (!$dbman->table_exists($table)) {
1679 // Adding fields to table adminpresets_app_plug.
1680 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1681 $table->add_field('adminpresetapplyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
1682 $table->add_field('plugin', XMLDB_TYPE_CHAR, '100', null, null, null, null);
1683 $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null);
1684 $table->add_field('value', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0');
1685 $table->add_field('oldvalue', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0');
1686
1687 // Adding keys to table adminpresets_app_plug.
1688 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
1689
1690 // Adding indexes to table adminpresets_app_plug.
1691 $table->add_index('adminpresetapplyid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetapplyid']);
1692
1693 // Launch create table for adminpresets_app_plug.
1694 if (!$dbman->table_exists($table)) {
1695 $dbman->create_table($table);
1696 }
1697 }
1698
1699 if ($DB->count_records('adminpresets', ['iscore' => 1]) == 0) {
1700 // Create default core site admin presets.
fc082d34 1701 require_once($CFG->dirroot . '/admin/presets/classes/helper.php');
727f0d4d
SA
1702 \core_adminpresets\helper::create_default_presets();
1703 }
1704
1705 // Main savepoint reached.
1706 upgrade_main_savepoint(true, 2021123000.01);
1707 }
1708
1f47ef1a
SA
1709 if ($oldversion < 2021123000.02) {
1710 // If exists, migrate sensiblesettings admin settings from tool_admin_preset to adminpresets.
1711 if (get_config('tool_admin_presets', 'sensiblesettings') !== false) {
1712 set_config('sensiblesettings', get_config('tool_admin_presets', 'sensiblesettings'), 'adminpresets');
1713 unset_config('sensiblesettings', 'tool_admin_presets');
1714 }
1715
1716 // Main savepoint reached.
1717 upgrade_main_savepoint(true, 2021123000.02);
1718 }
1719
e5a1b336
SA
1720 if ($oldversion < 2021123000.03) {
1721 // If exists, migrate lastpresetapplied setting from tool_admin_preset to adminpresets.
1722 if (get_config('tool_admin_presets', 'lastpresetapplied') !== false) {
1723 set_config('lastpresetapplied', get_config('tool_admin_presets', 'lastpresetapplied'), 'adminpresets');
1724 unset_config('lastpresetapplied', 'tool_admin_presets');
1725 }
1726
1727 // Main savepoint reached.
1728 upgrade_main_savepoint(true, 2021123000.03);
1729 }
1730
749c678e
SA
1731 if ($oldversion < 2022011100.01) {
1732 // The following blocks have been hidden by default, so they shouldn't be enabled in the Full core preset: Course/site
1733 // summary, RSS feeds, Self completion and Feedback.
7a6d0015
AA
1734 $params = ['name' => get_string('fullpreset', 'core_adminpresets')];
1735 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params);
749c678e 1736
77ca86bf
AA
1737 if (!$fullpreset) {
1738 // Full admin preset might have been created using the English name.
1739 $name = get_string_manager()->get_string('fullpreset', 'core_adminpresets', null, 'en');
1740 $params['name'] = $name;
7a6d0015 1741 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params);
77ca86bf
AA
1742 }
1743 if (!$fullpreset) {
1744 // We tried, but we didn't find full by name. Let's find a core preset that sets 'usecomments' setting to 1.
1745 $sql = "SELECT preset.*
1746 FROM {adminpresets} preset
1747 INNER JOIN {adminpresets_it} it ON preset.id = it.adminpresetid
7a6d0015 1748 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0";
77ca86bf
AA
1749 $params = ['name' => 'usecomments', 'value' => '1'];
1750 $fullpreset = $DB->get_record_sql($sql, $params);
1751 }
1752
749c678e
SA
1753 if ($fullpreset) {
1754 $blocknames = ['course_summary', 'feedback', 'rss_client', 'selfcompletion'];
1755 list($blocksinsql, $blocksinparams) = $DB->get_in_or_equal($blocknames);
1756
1757 // Remove entries from the adminpresets_app_plug table (in case the preset has been applied).
1758 $appliedpresets = $DB->get_records('adminpresets_app', ['adminpresetid' => $fullpreset->id], '', 'id');
1759 if ($appliedpresets) {
1760 list($appsinsql, $appsinparams) = $DB->get_in_or_equal(array_keys($appliedpresets));
1761 $sql = "adminpresetapplyid $appsinsql AND plugin='block' AND name $blocksinsql";
1762 $params = array_merge($appsinparams, $blocksinparams);
1763 $DB->delete_records_select('adminpresets_app_plug', $sql, $params);
1764 }
1765
1766 // Remove entries for these blocks from the adminpresets_plug table.
1767 $sql = "adminpresetid = ? AND plugin='block' AND name $blocksinsql";
1768 $params = array_merge([$fullpreset->id], $blocksinparams);
1769 $DB->delete_records_select('adminpresets_plug', $sql, $params);
1770 }
1771
1772 // Main savepoint reached.
1773 upgrade_main_savepoint(true, 2022011100.01);
1774 }
1775
57fe1a30 1776 if ($oldversion < 2022012100.02) {
e8ad1eaa
PFO
1777 // Migrate default message output config.
1778 $preferences = get_config('message');
1779
1780 $treatedprefs = [];
1781
1782 foreach ($preferences as $preference => $value) {
1783 // Extract provider and preference name from the setting name.
1784 // Example name: airnotifier_provider_enrol_imsenterprise_imsenterprise_enrolment_permitted
1785 // Provider: airnotifier
1786 // Preference: enrol_imsenterprise_imsenterprise_enrolment_permitted.
1787 $providerparts = explode('_provider_', $preference);
1788 if (count($providerparts) <= 1) {
1789 continue;
1790 }
1791
1792 $provider = $providerparts[0];
1793 $preference = $providerparts[1];
1794
1795 // Extract and remove last part of the preference previously extracted: ie. permitted.
1796 $parts = explode('_', $preference);
1797 $key = array_pop($parts);
1798
1799 if (in_array($key, ['permitted', 'loggedin', 'loggedoff'])) {
1800 if ($key == 'permitted') {
1801 // We will use provider name instead of permitted.
1802 $key = $provider;
1803 } else {
1804 // Logged in and logged off values are a csv of the enabled providers.
1805 $value = explode(',', $value);
1806 }
1807
1808 // Join the rest of the parts: ie enrol_imsenterprise_imsenterprise_enrolment.
1809 $prefname = implode('_', $parts);
1810
1811 if (!isset($treatedprefs[$prefname])) {
1812 $treatedprefs[$prefname] = [];
1813 }
1814
1815 // Save the value with the selected key.
1816 $treatedprefs[$prefname][$key] = $value;
1817 }
1818 }
1819
1820 // Now take every preference previous treated and its values.
1821 foreach ($treatedprefs as $prefname => $values) {
1822 $enabled = []; // List of providers enabled for each preference.
1823
1824 // Enable if one of those is enabled.
1825 $loggedin = isset($values['loggedin']) ? $values['loggedin'] : [];
1826 foreach ($loggedin as $provider) {
1827 $enabled[$provider] = 1;
1828 }
1829 $loggedoff = isset($values['loggedoff']) ? $values['loggedoff'] : [];
1830 foreach ($loggedoff as $provider) {
1831 $enabled[$provider] = 1;
1832 }
1833
1834 // Do not treat those values again.
1835 unset($values['loggedin']);
1836 unset($values['loggedoff']);
1837
1838 // Translate rest of values coming from permitted "key".
1839 foreach ($values as $provider => $value) {
1840 $locked = false;
1841
1842 switch ($value) {
1843 case 'forced':
1844 // Provider is enabled by force.
1845 $enabled[$provider] = 1;
1846 $locked = true;
1847 break;
1848 case 'disallowed':
1849 // Provider is disabled by force.
1850 unset($enabled[$provider]);
1851 $locked = true;
1852 break;
1853 default:
1854 // Provider is not forced (permitted) or invalid values.
1855 }
1856
1857 // Save locked.
1858 if ($locked) {
1859 set_config($provider.'_provider_'.$prefname.'_locked', 1, 'message');
acca36d2
AA
1860 } else {
1861 set_config($provider.'_provider_'.$prefname.'_locked', 0, 'message');
e8ad1eaa
PFO
1862 }
1863 // Remove old value.
1864 unset_config($provider.'_provider_'.$prefname.'_permitted', 'message');
1865 }
1866
1867 // Save the new values.
1868 $value = implode(',', array_keys($enabled));
1869 set_config('message_provider_'.$prefname.'_enabled', $value, 'message');
1870 // Remove old values.
1871 unset_config('message_provider_'.$prefname.'_loggedin', 'message');
1872 unset_config('message_provider_'.$prefname.'_loggedoff', 'message');
1873 }
1874
1875 // Migrate user preferences. ie merging message_provider_moodle_instantmessage_loggedoff with
1876 // message_provider_moodle_instantmessage_loggedin to message_provider_moodle_instantmessage_enabled.
1877
1878 $allrecordsloggedoff = $DB->sql_like('name', ':loggedoff');
1879 $total = $DB->count_records_select(
1880 'user_preferences',
1881 $allrecordsloggedoff,
1882 ['loggedoff' => 'message_provider_%_loggedoff']
1883 );
1884 $i = 0;
1885 if ($total == 0) {
1886 $total = 1; // Avoid division by zero.
1887 }
1888
1889 // Show a progress bar.
1890 $pbar = new progress_bar('upgradeusernotificationpreferences', 500, true);
1891 $pbar->update($i, $total, "Upgrading user notifications preferences - $i/$total.");
1892
1893 // We're migrating provider per provider to reduce memory usage.
1894 $providers = $DB->get_records('message_providers', null, 'name');
1895 foreach ($providers as $provider) {
1896 // 60 minutes to migrate each provider.
1897 upgrade_set_timeout(3600);
1898 $componentproviderbase = 'message_provider_'.$provider->component.'_'.$provider->name;
1899
1900 $loggedinname = $componentproviderbase.'_loggedin';
1901 $loggedoffname = $componentproviderbase.'_loggedoff';
1902
1903 // Change loggedin to enabled.
1904 $enabledname = $componentproviderbase.'_enabled';
1905 $DB->set_field('user_preferences', 'name', $enabledname, ['name' => $loggedinname]);
1906
1907 $selectparams = [
1908 'enabled' => $enabledname,
1909 'loggedoff' => $loggedoffname,
1910 ];
1911 $sql = 'SELECT m1.id loggedoffid, m1.value as loggedoff, m2.value as enabled, m2.id as enabledid
1912 FROM
1913 (SELECT id, userid, value FROM {user_preferences} WHERE name = :loggedoff) m1
1914 LEFT JOIN
1915 (SELECT id, userid, value FROM {user_preferences} WHERE name = :enabled) m2
1916 ON m1.userid = m2.userid';
1917
1918 while (($rs = $DB->get_recordset_sql($sql, $selectparams, 0, 1000)) && $rs->valid()) {
1919 // 10 minutes for every chunk.
1920 upgrade_set_timeout(600);
1921
1922 $deleterecords = [];
1923 $changename = [];
1924 $changevalue = []; // Multidimensional array with possible values as key to reduce SQL queries.
1925 foreach ($rs as $record) {
1926 if (empty($record->enabledid)) {
1927 // Enabled does not exists, change the name.
1928 $changename[] = $record->loggedoffid;
1929 } else if ($record->enabledid != $record->loggedoff) {
1930 // Exist and values differ (checked on SQL), update the enabled record.
1931
1932 if ($record->enabled != 'none' && !empty($record->enabled)) {
1933 $enabledvalues = explode(',', $record->enabled);
1934 } else {
1935 $enabledvalues = [];
1936 }
1937
1938 if ($record->loggedoff != 'none' && !empty($record->loggedoff)) {
1939 $loggedoffvalues = explode(',', $record->loggedoff);
1940 } else {
1941 $loggedoffvalues = [];
1942 }
1943
1944 $values = array_unique(array_merge($enabledvalues, $loggedoffvalues));
1945 sort($values);
1946
1947 $newvalue = empty($values) ? 'none' : implode(',', $values);
1948 if (!isset($changevalue[$newvalue])) {
1949 $changevalue[$newvalue] = [];
1950 }
1951 $changevalue[$newvalue][] = $record->enabledid;
1952
1953 $deleterecords[] = $record->loggedoffid;
1954 } else {
1955 // They are the same, just delete loggedoff one.
1956 $deleterecords[] = $record->loggedoffid;
1957 }
1958 $i++;
1959 }
1960 $rs->close();
1961
1962 // Commit the changes.
1963 if (!empty($changename)) {
1964 $changenameparams = [
1965 'name' => $loggedoffname,
1966 ];
1967 $changenameselect = 'name = :name AND id IN (' . implode(',', $changename) . ')';
1968 $DB->set_field_select('user_preferences', 'name', $enabledname, $changenameselect, $changenameparams);
1969 }
1970
1971 if (!empty($changevalue)) {
1972 $changevalueparams = [
1973 'name' => $enabledname,
1974 ];
1975 foreach ($changevalue as $value => $ids) {
1976 $changevalueselect = 'name = :name AND id IN (' . implode(',', $ids) . ')';
1977 $DB->set_field_select('user_preferences', 'value', $value, $changevalueselect, $changevalueparams);
1978 }
1979 }
1980
1981 if (!empty($deleterecords)) {
1982 $deleteparams = [
1983 'name' => $loggedoffname,
1984 ];
1985 $deleteselect = 'name = :name AND id IN (' . implode(',', $deleterecords) . ')';
1986 $DB->delete_records_select('user_preferences', $deleteselect, $deleteparams);
1987 }
1988
1989 // Update progress.
1990 $pbar->update($i, $total, "Upgrading user notifications preferences - $i/$total.");
1991 }
1992 $rs->close();
1993
1994 // Delete the rest of loggedoff values (that are equal than enabled).
1995 $deleteparams = [
1996 'name' => $loggedoffname,
1997 ];
1998 $deleteselect = 'name = :name';
1999 $i += $DB->count_records_select('user_preferences', $deleteselect, $deleteparams);
2000 $DB->delete_records_select('user_preferences', $deleteselect, $deleteparams);
2001
2002 // Update progress.
2003 $pbar->update($i, $total, "Upgrading user notifications preferences - $i/$total.");
2004 }
2005
2006 core_plugin_manager::reset_caches();
2007
2008 // Delete the orphan records.
2009 $allrecordsparams = ['loggedin' => 'message_provider_%_loggedin', 'loggedoff' => 'message_provider_%_loggedoff'];
2010 $allrecordsloggedin = $DB->sql_like('name', ':loggedin');
2011 $allrecordsloggedinoffsql = "$allrecordsloggedin OR $allrecordsloggedoff";
2012 $DB->delete_records_select('user_preferences', $allrecordsloggedinoffsql, $allrecordsparams);
2013
2014 // Update progress.
2015 $pbar->update($total, $total, "Upgrading user notifications preferences - $total/$total.");
2016
57fe1a30 2017 upgrade_main_savepoint(true, 2022012100.02);
e8ad1eaa
PFO
2018 }
2019
c34b89a3
GG
2020 // Introduce question versioning to core.
2021 // First, create the new tables.
2022 if ($oldversion < 2022020200.01) {
2023 // Define table question_bank_entries to be created.
2024 $table = new xmldb_table('question_bank_entries');
2025
2026 // Adding fields to table question_bank_entries.
2027 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2028 $table->add_field('questioncategoryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0);
2029 $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null);
2030 $table->add_field('ownerid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2031
2032 // Adding keys to table question_bank_entries.
2033 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2034 $table->add_key('questioncategoryid', XMLDB_KEY_FOREIGN, ['questioncategoryid'], 'question_categories', ['id']);
2035 $table->add_key('ownerid', XMLDB_KEY_FOREIGN, ['ownerid'], 'user', ['id']);
2036
2037 // Conditionally launch create table for question_bank_entries.
2038 if (!$dbman->table_exists($table)) {
2039 $dbman->create_table($table);
2040 }
2041
2042 // Create category id and id number index.
2043 $index = new xmldb_index('categoryidnumber', XMLDB_INDEX_UNIQUE, ['questioncategoryid', 'idnumber']);
2044
2045 // Conditionally launch add index categoryidnumber.
2046 if (!$dbman->index_exists($table, $index)) {
2047 $dbman->add_index($table, $index);
2048 }
2049
2050 // Define table question_versions to be created.
2051 $table = new xmldb_table('question_versions');
2052
2053 // Adding fields to table question_versions.
2054 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
1d0609bb 2055 $table->add_field('questionbankentryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0);
c34b89a3
GG
2056 $table->add_field('version', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 1);
2057 $table->add_field('questionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0);
2058 $table->add_field('status', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, 'ready');
2059
2060 // Adding keys to table question_versions.
2061 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2062 $table->add_key('questionbankentryid', XMLDB_KEY_FOREIGN, ['questionbankentryid'], 'question_bank_entries', ['id']);
2063 $table->add_key('questionid', XMLDB_KEY_FOREIGN, ['questionid'], 'question', ['id']);
2064
2065 // Conditionally launch create table for question_versions.
2066 if (!$dbman->table_exists($table)) {
2067 $dbman->create_table($table);
2068 }
2069
2070 // Define table question_references to be created.
2071 $table = new xmldb_table('question_references');
2072
2073 // Adding fields to table question_references.
2074 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2075 $table->add_field('usingcontextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0);
2076 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null);
2077 $table->add_field('questionarea', XMLDB_TYPE_CHAR, '50', null, null, null, null);
1d0609bb
SA
2078 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2079 $table->add_field('questionbankentryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0);
c34b89a3
GG
2080 $table->add_field('version', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
2081
2082 // Adding keys to table question_references.
2083 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2084 $table->add_key('usingcontextid', XMLDB_KEY_FOREIGN, ['usingcontextid'], 'context', ['id']);
2085 $table->add_key('questionbankentryid', XMLDB_KEY_FOREIGN, ['questionbankentryid'], 'question_bank_entries', ['id']);
2086
2087 // Conditionally launch create table for question_references.
2088 if (!$dbman->table_exists($table)) {
2089 $dbman->create_table($table);
2090 }
2091
2092 // Define table question_set_references to be created.
2093 $table = new xmldb_table('question_set_references');
2094
2095 // Adding fields to table question_set_references.
2096 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2097 $table->add_field('usingcontextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0);
2098 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null);
2099 $table->add_field('questionarea', XMLDB_TYPE_CHAR, '50', null, null, null, null);
1d0609bb 2100 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
c34b89a3
GG
2101 $table->add_field('questionscontextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0);
2102 $table->add_field('filtercondition', XMLDB_TYPE_TEXT, null, null, null, null, null);
2103
2104 // Adding keys to table question_set_references.
2105 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2106 $table->add_key('usingcontextid', XMLDB_KEY_FOREIGN, ['usingcontextid'], 'context', ['id']);
c34b89a3
GG
2107 $table->add_key('questionscontextid', XMLDB_KEY_FOREIGN, ['questionscontextid'], 'context', ['id']);
2108
2109 // Conditionally launch create table for question_set_references.
2110 if (!$dbman->table_exists($table)) {
2111 $dbman->create_table($table);
2112 }
2113
2114 // Main savepoint reached.
2115 upgrade_main_savepoint(true, 2022020200.01);
2116 }
2117
2118 if ($oldversion < 2022020200.02) {
6045e6b6
SS
2119 // Define a new temporary field in the question_bank_entries tables.
2120 // Creating temporary field questionid to populate the data in question version table.
2121 // This will make sure the appropriate question id is inserted the version table without making any complex joins.
2122 $table = new xmldb_table('question_bank_entries');
89db4174 2123 $field = new xmldb_field('questionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL);
6045e6b6
SS
2124 if (!$dbman->field_exists($table, $field)) {
2125 $dbman->add_field($table, $field);
2126 }
2127
2128 $transaction = $DB->start_delegated_transaction();
2129 upgrade_set_timeout(3600);
2130 // Create the data for the question_bank_entries table with, including the new temporary field.
2131 $sql = <<<EOF
2132 INSERT INTO {question_bank_entries}
2133 (questionid, questioncategoryid, idnumber, ownerid)
2134 SELECT id, category, idnumber, createdby
2135 FROM {question} q
2136 EOF;
2137
2138 // Inserting question_bank_entries data.
2139 $DB->execute($sql);
2140
2141 $transaction->allow_commit();
2142
c34b89a3
GG
2143 // Main savepoint reached.
2144 upgrade_main_savepoint(true, 2022020200.02);
2145 }
2146
c34b89a3 2147 if ($oldversion < 2022020200.03) {
6045e6b6
SS
2148 $transaction = $DB->start_delegated_transaction();
2149 upgrade_set_timeout(3600);
2150 // Create the question_versions using that temporary field.
2151 $sql = <<<EOF
2152 INSERT INTO {question_versions}
2153 (questionbankentryid, questionid, status)
2154 SELECT
2155 qbe.id,
2156 q.id,
2157 CASE
2158 WHEN q.hidden > 0 THEN 'hidden'
2159 ELSE 'ready'
2160 END
2161 FROM {question_bank_entries} qbe
2162 INNER JOIN {question} q ON qbe.questionid = q.id
2163 EOF;
2164
2165 // Inserting question_versions data.
2166 $DB->execute($sql);
2167
2168 $transaction->allow_commit();
2169
2170 // Dropping temporary field questionid.
2171 $table = new xmldb_table('question_bank_entries');
89db4174 2172 $field = new xmldb_field('questionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL);
6045e6b6
SS
2173 if ($dbman->field_exists($table, $field)) {
2174 $dbman->drop_field($table, $field);
2175 }
2176
2177 // Main savepoint reached.
2178 upgrade_main_savepoint(true, 2022020200.03);
2179 }
2180
2181 if ($oldversion < 2022020200.04) {
2182 $transaction = $DB->start_delegated_transaction();
2183 upgrade_set_timeout(3600);
2184 // Create the base data for the random questions in the set_references table.
2185 // This covers most of the hard work in one go.
2186 $concat = $DB->sql_concat("'{\"questioncategoryid\":\"'", 'q.category', "'\",\"includingsubcategories\":\"'",
2187 'qs.includingsubcategories', "'\"}'");
2188 $sql = <<<EOF
2189 INSERT INTO {question_set_references}
2190 (usingcontextid, component, questionarea, itemid, questionscontextid, filtercondition)
2191 SELECT
2192 c.id,
2193 'mod_quiz',
2194 'slot',
2195 qs.id,
2196 qc.contextid,
2197 $concat
2198 FROM {question} q
2199 INNER JOIN {quiz_slots} qs on q.id = qs.questionid
2200 INNER JOIN {course_modules} cm ON cm.instance = qs.quizid AND cm.module = :quizmoduleid
2201 INNER JOIN {context} c ON cm.id = c.instanceid AND c.contextlevel = :contextmodule
2202 INNER JOIN {question_categories} qc ON qc.id = q.category
2203 WHERE q.qtype = :random
2204 EOF;
2205
2206 // Inserting question_set_references data.
2207 $DB->execute($sql, [
2208 'quizmoduleid' => $DB->get_field('modules', 'id', ['name' => 'quiz']),
2209 'contextmodule' => CONTEXT_MODULE,
2210 'random' => 'random',
2211 ]);
2212
2213 $transaction->allow_commit();
2214
2215 // Main savepoint reached.
2216 upgrade_main_savepoint(true, 2022020200.04);
2217 }
2218
2219 if ($oldversion < 2022020200.05) {
2220 $transaction = $DB->start_delegated_transaction();
2221 upgrade_set_timeout(3600);
2222
2223 // Count all the slot tags to be migrated (for progress bar).
2224 $total = $DB->count_records('quiz_slot_tags');
2225 $pbar = new progress_bar('migratequestiontags', 1000, true);
2226 $i = 0;
2227 // Updating slot_tags for random question tags.
2228 // Now fetch any quiz slot tags and update those slot details into the question_set_references.
2229 $slottags = $DB->get_recordset('quiz_slot_tags', [], 'slotid ASC');
2230
2231 $tagstrings = [];
2232 $lastslot = null;
2233 $runinsert = function (int $lastslot, array $tagstrings) use ($DB) {
2234 $conditiondata = $DB->get_field('question_set_references', 'filtercondition',
2235 ['itemid' => $lastslot, 'component' => 'mod_quiz', 'questionarea' => 'slot']);
307f8327
S
2236
2237 // It is possible to have leftover tags in the database, without a corresponding
2238 // slot, because of an old bugs (e.g. MDL-76193). Therefore, if the slot is not found,
2239 // we can safely discard these tags.
2240 if (!empty($conditiondata)) {
2241 $condition = json_decode($conditiondata);
2242 $condition->tags = $tagstrings;
2243 $DB->set_field('question_set_references', 'filtercondition', json_encode($condition),
2244 ['itemid' => $lastslot, 'component' => 'mod_quiz', 'questionarea' => 'slot']);
2245 }
6045e6b6
SS
2246 };
2247
2248 foreach ($slottags as $tag) {
2249 upgrade_set_timeout(3600);
2250 if ($lastslot && $tag->slotid != $lastslot) {
2251 if (!empty($tagstrings)) {
2252 // Insert the data.
2253 $runinsert($lastslot, $tagstrings);
2254 }
2255 // Prepare for the next slot id.
2256 $tagstrings = [];
2257 }
2258
2259 $lastslot = $tag->slotid;
2260 $tagstrings[] = "{$tag->tagid},{$tag->tagname}";
2261 // Update progress.
2262 $i++;
2263 $pbar->update($i, $total, "Migrating question tags - $i/$total.");
2264 }
2265 if ($tagstrings) {
2266 $runinsert($lastslot, $tagstrings);
2267 }
2268 $slottags->close();
2269
2270 $transaction->allow_commit();
2271 // Main savepoint reached.
2272 upgrade_main_savepoint(true, 2022020200.05);
2273 }
2274
2275 if ($oldversion < 2022020200.06) {
2276 $transaction = $DB->start_delegated_transaction();
2277 upgrade_set_timeout(3600);
2278 // Create question_references record for each question.
2279 // Except if qtype is random. That case is handled by question_set_reference.
2280 $sql = "INSERT INTO {question_references}
2281 (usingcontextid, component, questionarea, itemid, questionbankentryid)
2282 SELECT c.id, 'mod_quiz', 'slot', qs.id, qv.questionbankentryid
2283 FROM {question} q
2284 JOIN {question_versions} qv ON q.id = qv.questionid
2285 JOIN {quiz_slots} qs ON q.id = qs.questionid
2286 JOIN {modules} m ON m.name = 'quiz'
2287 JOIN {course_modules} cm ON cm.module = m.id AND cm.instance = qs.quizid
2288 JOIN {context} c ON c.instanceid = cm.id AND c.contextlevel = " . CONTEXT_MODULE . "
2289 WHERE q.qtype <> 'random'";
2290
2291 // Inserting question_references data.
2292 $DB->execute($sql);
2293
2294 $transaction->allow_commit();
2295 // Main savepoint reached.
2296 upgrade_main_savepoint(true, 2022020200.06);
2297 }
2298
2299 // Finally, drop fields from question table.
2300 if ($oldversion < 2022020200.07) {
c34b89a3
GG
2301 // Define fields to be dropped from questions.
2302 $table = new xmldb_table('question');
2303
2304 $field = new xmldb_field('version');
2305 // Conditionally launch drop field version.
2306 if ($dbman->field_exists($table, $field)) {
2307 $dbman->drop_field($table, $field);
2308 }
2309
2310 $field = new xmldb_field('hidden');
2311 // Conditionally launch drop field hidden.
2312 if ($dbman->field_exists($table, $field)) {
2313 $dbman->drop_field($table, $field);
2314 }
2315
2316 // Define index categoryidnumber (not unique) to be dropped form question.
2317 $index = new xmldb_index('categoryidnumber', XMLDB_INDEX_UNIQUE, ['category', 'idnumber']);
2318
2319 // Conditionally launch drop index categoryidnumber.
2320 if ($dbman->index_exists($table, $index)) {
2321 $dbman->drop_index($table, $index);
2322 }
2323
2324 // Define key category (foreign) to be dropped form questions.
2325 $key = new xmldb_key('category', XMLDB_KEY_FOREIGN, ['category'], 'question_categories', ['id']);
2326
2327 // Launch drop key category.
2328 $dbman->drop_key($table, $key);
2329
2330 $field = new xmldb_field('idnumber');
2331 // Conditionally launch drop field idnumber.
2332 if ($dbman->field_exists($table, $field)) {
2333 $dbman->drop_field($table, $field);
2334 }
2335
2336 $field = new xmldb_field('category');
2337 // Conditionally launch drop field category.
2338 if ($dbman->field_exists($table, $field)) {
2339 $dbman->drop_field($table, $field);
2340 }
2341
2342 // Main savepoint reached.
6045e6b6 2343 upgrade_main_savepoint(true, 2022020200.07);
c34b89a3
GG
2344 }
2345
256232ad 2346 if ($oldversion < 2022021100.01) {
77ca86bf
AA
2347 $sql = "SELECT preset.*
2348 FROM {adminpresets} preset
2349 INNER JOIN {adminpresets_it} it ON preset.id = it.adminpresetid
7a6d0015 2350 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0";
256232ad
SA
2351 // Some settings and plugins have been added/removed to the Starter and Full preset. Add them to the core presets if
2352 // they haven't been included yet.
2353 $params = ['name' => get_string('starterpreset', 'core_adminpresets'), 'iscore' => 1];
2354 $starterpreset = $DB->get_record('adminpresets', $params);
77ca86bf
AA
2355 if (!$starterpreset) {
2356 // Starter admin preset might have been created using the English name.
2357 $name = get_string_manager()->get_string('starterpreset', 'core_adminpresets', null, 'en');
2358 $params['name'] = $name;
2359 $starterpreset = $DB->get_record('adminpresets', $params);
2360 }
2361 if (!$starterpreset) {
2362 // We tried, but we didn't find starter by name. Let's find a core preset that sets 'usecomments' setting to 0.
2363 $params = ['name' => 'usecomments', 'value' => '0'];
2364 $starterpreset = $DB->get_record_sql($sql, $params);
2365 }
2366
7a6d0015
AA
2367 $params = ['name' => get_string('fullpreset', 'core_adminpresets')];
2368 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params);
77ca86bf
AA
2369 if (!$fullpreset) {
2370 // Full admin preset might have been created using the English name.
2371 $name = get_string_manager()->get_string('fullpreset', 'core_adminpresets', null, 'en');
2372 $params['name'] = $name;
7a6d0015 2373 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params);
77ca86bf
AA
2374 }
2375 if (!$fullpreset) {
2376 // We tried, but we didn't find full by name. Let's find a core preset that sets 'usecomments' setting to 1.
2377 $params = ['name' => 'usecomments', 'value' => '1'];
2378 $fullpreset = $DB->get_record_sql($sql, $params);
2379 }
256232ad
SA
2380
2381 $settings = [
2382 // Settings. Hide Guest login button for Starter preset (and back to show for Full).
2383 [
2384 'presetid' => $starterpreset->id,
2385 'plugin' => 'none',
2386 'name' => 'guestloginbutton',
2387 'value' => '0',
2388 ],
2389 [
2390 'presetid' => $fullpreset->id,
2391 'plugin' => 'none',
2392 'name' => 'guestloginbutton',
2393 'value' => '1',
2394 ],
2395 // Settings. Set Activity chooser tabs to "Starred, All, Recommended"(1) for Starter and back it to default(0) for Full.
2396 [
2397 'presetid' => $starterpreset->id,
2398 'plugin' => 'none',
2399 'name' => 'activitychoosertabmode',
2400 'value' => '1',
2401 ],
2402 [
2403 'presetid' => $fullpreset->id,
2404 'plugin' => 'none',
2405 'name' => 'activitychoosertabmode',
2406 'value' => '0',
2407 ],
2408 ];
2409 foreach ($settings as $notused => $setting) {
2410 $params = ['adminpresetid' => $setting['presetid'], 'plugin' => $setting['plugin'], 'name' => $setting['name']];
2411 if (!$DB->record_exists('adminpresets_it', $params)) {
2412 $record = new \stdClass();
2413 $record->adminpresetid = $setting['presetid'];
2414 $record->plugin = $setting['plugin'];
2415 $record->name = $setting['name'];
2416 $record->value = $setting['value'];
2417 $DB->insert_record('adminpresets_it', $record);
2418 }
2419 }
2420
2421 $plugins = [
2422 // Plugins. Blocks. Disable/enable Online users, Recently accessed courses and Starred courses.
2423 [
2424 'presetid' => $starterpreset->id,
2425 'plugin' => 'block',
2426 'name' => 'online_users',
2427 'enabled' => '0',
2428 ],
2429 [
2430 'presetid' => $fullpreset->id,
2431 'plugin' => 'block',
2432 'name' => 'online_users',
2433 'enabled' => '1',
2434 ],
2435 [
2436 'presetid' => $starterpreset->id,
2437 'plugin' => 'block',
2438 'name' => 'recentlyaccessedcourses',
2439 'enabled' => '0',
2440 ],
2441 [
2442 'presetid' => $fullpreset->id,
2443 'plugin' => 'block',
2444 'name' => 'recentlyaccessedcourses',
2445 'enabled' => '1',
2446 ],
2447 [
2448 'presetid' => $starterpreset->id,
2449 'plugin' => 'block',
2450 'name' => 'starredcourses',
2451 'enabled' => '0',
2452 ],
2453 [
2454 'presetid' => $fullpreset->id,
2455 'plugin' => 'block',
2456 'name' => 'starredcourses',
2457 'enabled' => '1',
2458 ],
2459 // Plugins. Enrolments. Disable/enable Guest access.
2460 [
2461 'presetid' => $starterpreset->id,
2462 'plugin' => 'enrol',
2463 'name' => 'guest',
2464 'enabled' => '0',
2465 ],
2466 [
2467 'presetid' => $fullpreset->id,
2468 'plugin' => 'enrol',
2469 'name' => 'guest',
2470 'enabled' => '1',
2471 ],
2472 ];
2473 foreach ($plugins as $notused => $plugin) {
2474 $params = ['adminpresetid' => $plugin['presetid'], 'plugin' => $plugin['plugin'], 'name' => $plugin['name']];
2475 if (!$DB->record_exists('adminpresets_plug', $params)) {
2476 $record = new \stdClass();
2477 $record->adminpresetid = $plugin['presetid'];
2478 $record->plugin = $plugin['plugin'];
2479 $record->name = $plugin['name'];
2480 $record->enabled = $plugin['enabled'];
2481 $DB->insert_record('adminpresets_plug', $record);
2482 }
2483 }
2484
2485 // Settings: Remove customusermenuitems setting from Starter and Full presets.
2486 $sql = "(adminpresetid = ? OR adminpresetid = ?) AND plugin = 'none' AND name = 'customusermenuitems'";
2487 $params = [$starterpreset->id, $fullpreset->id];
2488 $DB->delete_records_select('adminpresets_it', $sql, $params);
2489
2490 // Plugins. Question types. Re-enable Description and Essay for Starter.
2491 $sql = "(adminpresetid = ? OR adminpresetid = ?) AND plugin = 'qtype' AND (name = 'description' OR name = 'essay')";
2492 $DB->delete_records_select('adminpresets_plug', $sql, $params);
2493
2494 // Main savepoint reached.
2495 upgrade_main_savepoint(true, 2022021100.01);
dfa0681c
IT
2496
2497 }
2498
2499 if ($oldversion < 2022021100.02) {
21f73b29
JPA
2500 $table = new xmldb_table('task_scheduled');
2501
2502 // Changing precision of field minute on table task_scheduled to (200).
2503 $field = new xmldb_field('minute', XMLDB_TYPE_CHAR, '200', null, XMLDB_NOTNULL, null, null, 'blocking');
2504 $dbman->change_field_precision($table, $field);
2505 // Changing precision of field hour on table task_scheduled to (70).
2506 $field = new xmldb_field('hour', XMLDB_TYPE_CHAR, '70', null, XMLDB_NOTNULL, null, null, 'minute');
2507 $dbman->change_field_precision($table, $field);
2508 // Changing precision of field day on table task_scheduled to (90).
2509 $field = new xmldb_field('day', XMLDB_TYPE_CHAR, '90', null, XMLDB_NOTNULL, null, null, 'hour');
2510 $dbman->change_field_precision($table, $field);
2511 // Changing precision of field month on table task_scheduled to (30).
2512 $field = new xmldb_field('month', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null, 'day');
2513 $dbman->change_field_precision($table, $field);
2514
2515 // Main savepoint reached.
dfa0681c 2516 upgrade_main_savepoint(true, 2022021100.02);
256232ad
SA
2517 }
2518
acca36d2
AA
2519 if ($oldversion < 2022022600.01) {
2520 // Get all processor and existing preferences.
2521 $processors = $DB->get_records('message_processors');
2522 $providers = $DB->get_records('message_providers', null, '', 'id, name, component');
2523 $existingpreferences = get_config('message');
2524
2525 foreach ($processors as $processor) {
2526 foreach ($providers as $provider) {
2527 // Setting default preference name.
2528 $componentproviderbase = $provider->component . '_' . $provider->name;
2529 $preferencename = $processor->name.'_provider_'.$componentproviderbase.'_locked';
2530 // If we do not have this setting yet, set it to 0.
2531 if (!isset($existingpreferences->{$preferencename})) {
2532 set_config($preferencename, 0, 'message');
2533 }
2534 }
2535 }
2536
2537 upgrade_main_savepoint(true, 2022022600.01);
2538 }
2539
c0196fb0
AA
2540 if ($oldversion < 2022030100.00) {
2541 $sql = "SELECT preset.*
2542 FROM {adminpresets} preset
2543 INNER JOIN {adminpresets_it} it ON preset.id = it.adminpresetid
7a6d0015 2544 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0";
c0196fb0
AA
2545
2546 $name = get_string('starterpreset', 'core_adminpresets');
2547 $params = ['name' => $name, 'iscore' => 1];
2548 $starterpreset = $DB->get_record('adminpresets', $params);
2549 if (!$starterpreset) {
2550 // Starter admin preset might have been created using the English name. Let's change it to current language.
2551 $englishname = get_string_manager()->get_string('starterpreset', 'core_adminpresets', null, 'en');
2552 $params['name'] = $englishname;
2553 $starterpreset = $DB->get_record('adminpresets', $params);
2554 }
2555 if (!$starterpreset) {
2556 // We tried, but we didn't find starter by name. Let's find a core preset that sets 'usecomments' setting to 0.
2557 $params = ['name' => 'usecomments', 'value' => '0'];
2558 $starterpreset = $DB->get_record_sql($sql, $params);
2559 }
2560 // The iscore field is already 1 for starterpreset, so we don't need to change it.
2561 // We only need to update the name and comment in case they are different to current language strings.
2562 if ($starterpreset && $starterpreset->name != $name) {
2563 $starterpreset->name = $name;
2564 $starterpreset->comments = get_string('starterpresetdescription', 'core_adminpresets');
2565 $DB->update_record('adminpresets', $starterpreset);
2566 }
2567
2568 // Let's mark Full admin presets with current FULL_PRESETS value and change the name to current language.
2569 $name = get_string('fullpreset', 'core_adminpresets');
7a6d0015
AA
2570 $params = ['name' => $name];
2571 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params);
c0196fb0
AA
2572 if (!$fullpreset) {
2573 // Full admin preset might have been created using the English name.
2574 $englishname = get_string_manager()->get_string('fullpreset', 'core_adminpresets', null, 'en');
2575 $params['name'] = $englishname;
7a6d0015 2576 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params);
c0196fb0
AA
2577 }
2578 if (!$fullpreset) {
2579 // We tried, but we didn't find full by name. Let's find a core preset that sets 'usecomments' setting to 1.
2580 $params = ['name' => 'usecomments', 'value' => '1'];
2581 $fullpreset = $DB->get_record_sql($sql, $params);
2582 }
2583 if ($fullpreset) {
2584 // We need to update iscore field value, whether the name is the same or not.
2585 $fullpreset->name = $name;
2586 $fullpreset->comments = get_string('fullpresetdescription', 'core_adminpresets');
2587 $fullpreset->iscore = 2;
2588 $DB->update_record('adminpresets', $fullpreset);
534cc4da
AA
2589
2590 // We are applying again changes made on 2022011100.01 upgrading step because of MDL-73953 bug.
2591 $blocknames = ['course_summary', 'feedback', 'rss_client', 'selfcompletion'];
2592 list($blocksinsql, $blocksinparams) = $DB->get_in_or_equal($blocknames);
2593
2594 // Remove entries from the adminpresets_app_plug table (in case the preset has been applied).
2595 $appliedpresets = $DB->get_records('adminpresets_app', ['adminpresetid' => $fullpreset->id], '', 'id');
2596 if ($appliedpresets) {
2597 list($appsinsql, $appsinparams) = $DB->get_in_or_equal(array_keys($appliedpresets));
2598 $sql = "adminpresetapplyid $appsinsql AND plugin='block' AND name $blocksinsql";
2599 $params = array_merge($appsinparams, $blocksinparams);
2600 $DB->delete_records_select('adminpresets_app_plug', $sql, $params);
2601 }
2602
2603 // Remove entries for these blocks from the adminpresets_plug table.
2604 $sql = "adminpresetid = ? AND plugin='block' AND name $blocksinsql";
2605 $params = array_merge([$fullpreset->id], $blocksinparams);
2606 $DB->delete_records_select('adminpresets_plug', $sql, $params);
c0196fb0
AA
2607 }
2608
2609 // Main savepoint reached.
2610 upgrade_main_savepoint(true, 2022030100.00);
2611 }
2612
e95d99eb 2613 if ($oldversion < 2022031100.01) {
d2acd089
MM
2614 $reportsusermenuitem = 'reports,core_reportbuilder|/reportbuilder/index.php';
2615 upgrade_add_item_to_usermenu($reportsusermenuitem);
2616 // Main savepoint reached.
e95d99eb 2617 upgrade_main_savepoint(true, 2022031100.01);
d2acd089
MM
2618 }
2619
7bedf54f 2620 if ($oldversion < 2022032200.01) {
c3ac868b
MAG
2621
2622 // Define index to be added to question_references.
2623 $table = new xmldb_table('question_references');
2624 $index = new xmldb_index('context-component-area-itemid', XMLDB_INDEX_UNIQUE,
2625 ['usingcontextid', 'component', 'questionarea', 'itemid']);
2626
2627 // Conditionally launch add field id.
2628 if (!$dbman->index_exists($table, $index)) {
2629 $dbman->add_index($table, $index);
2630 }
2631
2632 // Main savepoint reached.
7bedf54f 2633 upgrade_main_savepoint(true, 2022032200.01);
c3ac868b
MAG
2634 }
2635
7bedf54f 2636 if ($oldversion < 2022032200.02) {
c3ac868b
MAG
2637
2638 // Define index to be added to question_references.
2639 $table = new xmldb_table('question_set_references');
2640 $index = new xmldb_index('context-component-area-itemid', XMLDB_INDEX_UNIQUE,
2641 ['usingcontextid', 'component', 'questionarea', 'itemid']);
2642
2643 // Conditionally launch add field id.
2644 if (!$dbman->index_exists($table, $index)) {
2645 $dbman->add_index($table, $index);
2646 }
2647
2648 // Main savepoint reached.
7bedf54f 2649 upgrade_main_savepoint(true, 2022032200.02);
c3ac868b
MAG
2650 }
2651
a3a473d6
PH
2652 if ($oldversion < 2022041200.01) {
2653
2654 // The original default admin presets "sensible settings" (those that should be treated as sensitive).
2655 $originalsensiblesettings = 'recaptchapublickey@@none, recaptchaprivatekey@@none, googlemapkey3@@none, ' .
2656 'secretphrase@@url, cronremotepassword@@none, smtpuser@@none, smtppass@none, proxypassword@@none, ' .
2657 'quizpassword@@quiz, allowedip@@none, blockedip@@none, dbpass@@logstore_database, messageinbound_hostpass@@none, ' .
2658 'bind_pw@@auth_cas, pass@@auth_db, bind_pw@@auth_ldap, dbpass@@enrol_database, bind_pw@@enrol_ldap, ' .
2659 'server_password@@search_solr, ssl_keypassword@@search_solr, alternateserver_password@@search_solr, ' .
2660 'alternatessl_keypassword@@search_solr, test_password@@cachestore_redis, password@@mlbackend_python';
2661
2662 // Check if the current config matches the original default, upgrade to new default if so.
2663 if (get_config('adminpresets', 'sensiblesettings') === $originalsensiblesettings) {
2664 $newsensiblesettings = "{$originalsensiblesettings}, badges_badgesalt@@none, calendar_exportsalt@@none";
2665 set_config('sensiblesettings', $newsensiblesettings, 'adminpresets');
2666 }
2667
2668 // Main savepoint reached.
2669 upgrade_main_savepoint(true, 2022041200.01);
2670 }
2671
76f54454
EL
2672 // Automatically generated Moodle v4.0.0 release upgrade line.
2673 // Put any upgrade step following this.
2674
ffc655b1
AA
2675 if ($oldversion < 2022042900.01) {
2676 // Social custom fields could had been created linked to category id = 1. Let's check category 1 exists.
2677 if (!$DB->get_record('user_info_category', ['id' => 1])) {
2678 // Let's check if we have any custom field linked to category id = 1.
2679 $fields = $DB->get_records('user_info_field', ['categoryid' => 1]);
2680 if (!empty($fields)) {
2681 $categoryid = $DB->get_field_sql('SELECT min(id) from {user_info_category}');
2682 foreach ($fields as $field) {
2683 $field->categoryid = $categoryid;
2684 $DB->update_record('user_info_field', $field);
2685 }
2686 }
2687 }
2688
2689 // Main savepoint reached.
2690 upgrade_main_savepoint(true, 2022042900.01);
2691 }
2692
bc604115
PW
2693 if ($oldversion < 2022051000.00) {
2694 // Add index to the sid field in the external_tokens table.
2695 $table = new xmldb_table('external_tokens');
2696 $index = new xmldb_index('sid', XMLDB_INDEX_NOTUNIQUE, ['sid']);
2697
2698 if (!$dbman->index_exists($table, $index)) {
2699 $dbman->add_index($table, $index);
2700 }
2701
2702 upgrade_main_savepoint(true, 2022051000.00);
2703 }
2704
3801662e
PB
2705 if ($oldversion < 2022052500.00) {
2706 // Start an adhoc task to fix the file timestamps of restored files.
2707 $task = new core\task\fix_file_timestamps_task();
2708 \core\task\manager::queue_adhoc_task($task);
2709
2710 // Main savepoint reached.
2711 upgrade_main_savepoint(true, 2022052500.00);
2712 }
2713
0460147c 2714 if ($oldversion < 2022052700.01) {
8154aa2e
CB
2715
2716 // Define index timestarted_idx (not unique) to be added to task_adhoc.
2717 $table = new xmldb_table('task_adhoc');
2718 $index = new xmldb_index('timestarted_idx', XMLDB_INDEX_NOTUNIQUE, ['timestarted']);
2719
2720 // Conditionally launch add index timestarted_idx.
2721 if (!$dbman->index_exists($table, $index)) {
2722 $dbman->add_index($table, $index);
2723 }
2724
2725 // Main savepoint reached.
0460147c 2726 upgrade_main_savepoint(true, 2022052700.01);
8154aa2e
CB
2727 }
2728
df71afbf 2729 if ($oldversion < 2022052700.02) {
f984566b
KP
2730
2731 // Define index filename (not unique) to be added to files.
2732 $table = new xmldb_table('files');
2733 $index = new xmldb_index('filename', XMLDB_INDEX_NOTUNIQUE, ['filename']);
2734
2735 // Conditionally launch add index filename.
2736 if (!$dbman->index_exists($table, $index)) {
2737 $dbman->add_index($table, $index);
2738 }
2739
2740 // Main savepoint reached.
df71afbf 2741 upgrade_main_savepoint(true, 2022052700.02);
f984566b
KP
2742 }
2743
67b15496
PH
2744 if ($oldversion < 2022060300.01) {
2745
2746 // Changing precision of field hidden on table grade_categories to (10).
2747 $table = new xmldb_table('grade_categories');
2748 $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'timemodified');
2749
2750 // Launch change of precision for field hidden.
2751 $dbman->change_field_precision($table, $field);
2752
2753 // Changing precision of field hidden on table grade_categories_history to (10).
2754 $table = new xmldb_table('grade_categories_history');
2755 $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'aggregatesubcats');
2756
2757 // Launch change of precision for field hidden.
2758 $dbman->change_field_precision($table, $field);
2759
2760 // Main savepoint reached.
2761 upgrade_main_savepoint(true, 2022060300.01);
2762 }
2763
e1fefe2e
PH
2764 if ($oldversion < 2022061000.01) {
2765 // Iterate over custom user menu items configuration, removing pix icon references.
2766 $customusermenuitems = str_replace(["\r\n", "\r"], "\n", $CFG->customusermenuitems);
2767
2768 $lines = preg_split('/\n/', $customusermenuitems, -1, PREG_SPLIT_NO_EMPTY);
2769 $lines = array_map(static function(string $line): string {
2770 // Previous format was "<langstring>|<url>[|<pixicon>]" - pix icon is no longer supported.
2771 $lineparts = explode('|', trim($line), 3);
2772 // Return first two parts of line.
2773 return implode('|', array_slice($lineparts, 0, 2));
2774 }, $lines);
2775
2776 set_config('customusermenuitems', implode("\n", $lines));
2777
2778 upgrade_main_savepoint(true, 2022061000.01);
2779 }
2780
c3d4845d 2781 if ($oldversion < 2022061500.00) {
47d11994
PH
2782 // Remove drawer-open-nav user preference for every user.
2783 $DB->delete_records('user_preferences', ['name' => 'drawer-open-nav']);
2784
2785 // Main savepoint reached.
c3d4845d 2786 upgrade_main_savepoint(true, 2022061500.00);
af71e4f4
KP
2787
2788 }
2789
2790 if ($oldversion < 2022072900.00) {
2791 // Call the helper function that updates the foreign keys and indexes in MDL-49795.
2792 upgrade_add_foreign_key_and_indexes();
2793
2794 // Main savepoint reached.
2795 upgrade_main_savepoint(true, 2022072900.00);
47d11994
PH
2796 }
2797
8babdbd3
TH
2798 if ($oldversion < 2022081200.01) {
2799
2800 // Define field lang to be added to course_modules.
2801 $table = new xmldb_table('course_modules');
2802 $field = new xmldb_field('lang', XMLDB_TYPE_CHAR, '30', null, null, null, null, 'downloadcontent');
2803
2804 // Conditionally launch add field lang.
2805 if (!$dbman->field_exists($table, $field)) {
2806 $dbman->add_field($table, $field);
2807 }
2808
2809 // Main savepoint reached.
2810 upgrade_main_savepoint(true, 2022081200.01);
2811 }
2812
6330c482 2813 if ($oldversion < 2022091000.01) {
2814 $table = new xmldb_table('h5p');
2815 $indexpathnamehash = new xmldb_index('pathnamehash_idx', XMLDB_INDEX_NOTUNIQUE, ['pathnamehash']);
2816
2817 if (!$dbman->index_exists($table, $indexpathnamehash)) {
2818 $dbman->add_index($table, $indexpathnamehash);
2819 }
2820 // Main savepoint reached.
2821 upgrade_main_savepoint(true, 2022091000.01);
2822 }
2823
fd583ac9
PH
2824 if ($oldversion < 2022092200.01) {
2825
2826 // Remove any orphaned tag instance records (pointing to non-existing context).
2827 $DB->delete_records_select('tag_instance', 'NOT EXISTS (
2828 SELECT ctx.id FROM {context} ctx WHERE ctx.id = {tag_instance}.contextid
2829 )');
2830
2831 // Main savepoint reached.
2832 upgrade_main_savepoint(true, 2022092200.01);
2833 }
2834
cfb64329
MH
2835 if ($oldversion < 2022101400.01) {
2836 $table = new xmldb_table('competency_modulecomp');
2837 $field = new xmldb_field('overridegrade', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'ruleoutcome');
2838
2839 if (!$dbman->field_exists($table, $field)) {
2840 $dbman->add_field($table, $field);
2841 }
2842
2843 // Main savepoint reached.
2844 upgrade_main_savepoint(true, 2022101400.01);
2845 }
2846
d5e9b5ba 2847 if ($oldversion < 2022101400.03) {
c6e018e0 2848 // Define table to store completion viewed.
2849 $table = new xmldb_table('course_modules_viewed');
2850
2851 // Adding fields to table course_modules_viewed.
2852 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
2853 $table->add_field('coursemoduleid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
2854 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'coursemoduleid');
4272ccd6 2855 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'userid');
c6e018e0 2856
2857 // Adding keys to table course_modules_viewed.
2858 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
2859
2860 // Adding indexes to table course_modules_viewed.
2861 $table->add_index('coursemoduleid', XMLDB_INDEX_NOTUNIQUE, ['coursemoduleid']);
2862 $table->add_index('userid-coursemoduleid', XMLDB_INDEX_UNIQUE, ['userid', 'coursemoduleid']);
2863
2864 if (!$dbman->table_exists($table)) {
2865 $dbman->create_table($table);
2866 }
2867
2868 // Main savepoint reached.
d5e9b5ba 2869 upgrade_main_savepoint(true, 2022101400.03);
c6e018e0 2870 }
2871
d5e9b5ba 2872 if ($oldversion < 2022101400.04) {
c6e018e0 2873 // Add legacy data to the new table.
2874 $transaction = $DB->start_delegated_transaction();
2875 upgrade_set_timeout(3600);
2876 $sql = "INSERT INTO {course_modules_viewed}
2877 (userid, coursemoduleid, timecreated)
2878 SELECT userid, coursemoduleid, timemodified
2879 FROM {course_modules_completion}
2880 WHERE viewed = 1";
2881 $DB->execute($sql);
2882 $transaction->allow_commit();
2883
2884 // Main savepoint reached.
d5e9b5ba 2885 upgrade_main_savepoint(true, 2022101400.04);
c6e018e0 2886 }
2887
d5e9b5ba 2888 if ($oldversion < 2022101400.05) {
c6e018e0 2889 // Define field viewed to be dropped from course_modules_completion.
2890 $table = new xmldb_table('course_modules_completion');
2891 $field = new xmldb_field('viewed');
2892
2893 // Conditionally launch drop field viewed.
2894 if ($dbman->field_exists($table, $field)) {
2895 $dbman->drop_field($table, $field);
2896 }
2897
2898 // Main savepoint reached.
d5e9b5ba 2899 upgrade_main_savepoint(true, 2022101400.05);
c6e018e0 2900 }
2901
e3b3ba90
MH
2902 if ($oldversion < 2022102800.01) {
2903 // For sites with "contact site support" already available (4.0.x), maintain existing functionality.
2904 if ($oldversion >= 2022041900.00) {
2905 set_config('supportavailability', CONTACT_SUPPORT_ANYONE);
2906 } else {
2907 // Sites which did not previously have the "contact site support" feature default to it requiring authentication.
2908 set_config('supportavailability', CONTACT_SUPPORT_AUTHENTICATED);
2909 }
2910
2911 // Main savepoint reached.
2912 upgrade_main_savepoint(true, 2022102800.01);
2913 }
2914
df227f38
EL
2915 if ($oldversion < 2022110600.00) {
2916 // If webservice_xmlrpc isn't any longer installed, remove its configuration,
2917 // capabilities and presence in other settings.
2918 if (!file_exists($CFG->dirroot . '/webservice/xmlrpc/version.php')) {
2919 // No DB structures to delete in this plugin.
2920
2921 // Remove capabilities.
2922 capabilities_cleanup('webservice_xmlrpc');
2923
2924 // Remove own configuration.
2925 unset_all_config_for_plugin('webservice_xmlrpc');
2926
2927 // Remove it from the enabled protocols if it was there.
2928 $protos = get_config('core', 'webserviceprotocols');
2929 $protoarr = explode(',', $protos);
2930 $protoarr = array_filter($protoarr, function($ele) {
2931 return trim($ele) !== 'xmlrpc';
2932 });
2933 $protos = implode(',', $protoarr);
2934 set_config('webserviceprotocols', $protos);
2935 }
2936
2937 // Main savepoint reached.
2938 upgrade_main_savepoint(true, 2022110600.00);
2939 }
2940
c6ab792d
JP
2941 // Automatically generated Moodle v4.1.0 release upgrade line.
2942 // Put any upgrade step following this.
2943
7bab1754
PH
2944 if ($oldversion < 2022120900.01) {
2945
2946 // Remove any orphaned role assignment records (pointing to non-existing roles).
2947 $DB->delete_records_select('role_assignments', 'NOT EXISTS (
2948 SELECT r.id FROM {role} r WHERE r.id = {role_assignments}.roleid
2949 )');
2950
2951 // Main savepoint reached.
2952 upgrade_main_savepoint(true, 2022120900.01);
2953 }
2954
b4e5e47a
FK
2955 if ($oldversion < 2022121600.01) {
2956 // Define index blocknameindex (not unique) to be added to block_instances.
2957 $table = new xmldb_table('block_instances');
2958 $index = new xmldb_index('blocknameindex', XMLDB_INDEX_NOTUNIQUE, ['blockname']);
2959
2960 // Conditionally launch add index blocknameindex.
2961 if (!$dbman->index_exists($table, $index)) {
2962 $dbman->add_index($table, $index);
2963 }
2964 // Main savepoint reached.
2965 upgrade_main_savepoint(true, 2022121600.01);
2966 }
2967
1ac2eb53
AN
2968 if ($oldversion < 2023010300.00) {
2969 // The useexternalyui setting has been removed.
2970 unset_config('useexternalyui');
2971
2972 // Main savepoint reached.
2973 upgrade_main_savepoint(true, 2023010300.00);
2974 }
2975
5ab615c6 2976 if ($oldversion < 2023020800.00) {
7bf57d98
AN
2977 // If cachestore_memcached is no longer present, remove it.
2978 if (!file_exists($CFG->dirroot . '/cache/stores/memcached/version.php')) {
2979 // Clean config.
2980 unset_all_config_for_plugin('cachestore_memcached');
2981 }
2982
2983 // Main savepoint reached.
5ab615c6 2984 upgrade_main_savepoint(true, 2023020800.00);
7bf57d98
AN
2985 }
2986
9e725bc1
TT
2987 if ($oldversion < 2023021700.01) {
2988 // Define field pdfexportfont to be added to course.
2989 $table = new xmldb_table('course');
2990 $field = new xmldb_field('pdfexportfont', XMLDB_TYPE_CHAR, '50', null, false, false, null, 'showcompletionconditions');
2991
2992 // Conditionally launch add field pdfexportfont.
2993 if (!$dbman->field_exists($table, $field)) {
2994 $dbman->add_field($table, $field);
2995 }
2996
2997 // Main savepoint reached.
2998 upgrade_main_savepoint(true, 2023021700.01);
2999 }
3000
6111426f 3001 if ($oldversion < 2023022000.00) {
1b8ac1ff
IT
3002 // Remove grade_report_showquickfeedback, grade_report_enableajax, grade_report_showeyecons,
3003 // grade_report_showlocks, grade_report_showanalysisicon preferences for every user.
3004 $DB->delete_records('user_preferences', ['name' => 'grade_report_showquickfeedback']);
3005 $DB->delete_records('user_preferences', ['name' => 'grade_report_enableajax']);
3006 $DB->delete_records('user_preferences', ['name' => 'grade_report_showeyecons']);
3007 $DB->delete_records('user_preferences', ['name' => 'grade_report_showlocks']);
3008 $DB->delete_records('user_preferences', ['name' => 'grade_report_showanalysisicon']);
3009
3010 // The grade_report_showquickfeedback, grade_report_enableajax, grade_report_showeyecons,
3011 // grade_report_showlocks, grade_report_showanalysisicon settings have been removed.
3012 unset_config('grade_report_showquickfeedback');
3013 unset_config('grade_report_enableajax');
3014 unset_config('grade_report_showeyecons');
3015 unset_config('grade_report_showlocks');
3016 unset_config('grade_report_showanalysisicon');
3017
3018 // Main savepoint reached.
6111426f 3019 upgrade_main_savepoint(true, 2023022000.00);
1b8ac1ff
IT
3020 }
3021
5c20b537
SA
3022 if ($oldversion < 2023030300.01) {
3023 $sql = "SELECT preset.*
3024 FROM {adminpresets} preset
3025 INNER JOIN {adminpresets_it} it ON preset.id = it.adminpresetid
3026 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0";
3027 // Some settings and plugins have been added/removed to the Starter and Full preset. Add them to the core presets if
3028 // they haven't been included yet.
3029 $params = ['name' => get_string('starterpreset', 'core_adminpresets'), 'iscore' => 1];
3030 $starterpreset = $DB->get_record('adminpresets', $params);
3031 if (!$starterpreset) {
3032 // Starter admin preset might have been created using the English name.
3033 $name = get_string_manager()->get_string('starterpreset', 'core_adminpresets', null, 'en');
3034 $params['name'] = $name;
3035 $starterpreset = $DB->get_record('adminpresets', $params);
3036 }
3037 if (!$starterpreset) {
3038 // We tried, but we didn't find starter by name. Let's find a core preset that sets 'usecomments' setting to 0.
3039 $params = ['name' => 'usecomments', 'value' => '0'];
3040 $starterpreset = $DB->get_record_sql($sql, $params);
3041 }
3042
3043 $params = ['name' => get_string('fullpreset', 'core_adminpresets')];
3044 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params);
3045 if (!$fullpreset) {
3046 // Full admin preset might have been created using the English name.
3047 $name = get_string_manager()->get_string('fullpreset', 'core_adminpresets', null, 'en');
3048 $params['name'] = $name;
3049 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params);
3050 }
3051 if (!$fullpreset) {
3052 // We tried, but we didn't find full by name. Let's find a core preset that sets 'usecomments' setting to 1.
3053 $params = ['name' => 'usecomments', 'value' => '1'];
3054 $fullpreset = $DB->get_record_sql($sql, $params);
3055 }
3056
3057 $settings = [
3058 // Settings. Set Activity chooser tabs to "Starred, Recommended, All"(5) for Starter and back it to default(3) for Full.
3059 [
3060 'presetid' => $starterpreset->id,
3061 'plugin' => 'none',
3062 'name' => 'activitychoosertabmode',
3063 'value' => '4',
3064 ],
3065 [
3066 'presetid' => $fullpreset->id,
3067 'plugin' => 'none',
3068 'name' => 'activitychoosertabmode',
3069 'value' => '3',
3070 ],
3071 ];
3072 foreach ($settings as $notused => $setting) {
3073 $params = ['adminpresetid' => $setting['presetid'], 'plugin' => $setting['plugin'], 'name' => $setting['name']];
3074 if (!$record = $DB->get_record('adminpresets_it', $params)) {
3075 $record = new \stdClass();
3076 $record->adminpresetid = $setting['presetid'];
3077 $record->plugin = $setting['plugin'];
3078 $record->name = $setting['name'];
3079 $record->value = $setting['value'];
3080 $DB->insert_record('adminpresets_it', $record);
3081 } else {
3082 $record->value = $setting['value'];
3083 $DB->update_record('adminpresets_it', $record);
3084 }
3085 }
3086
3087 // Main savepoint reached.
3088 upgrade_main_savepoint(true, 2023030300.01);
3089 }
3090
25254cee 3091 if ($oldversion < 2023030300.02) {
8ae5ebb5
AN
3092 // If cachestore_mongodb is no longer present, remove it.
3093 if (!file_exists($CFG->dirroot . '/cache/stores/mongodb/version.php')) {
3094 // Clean config.
3095 unset_all_config_for_plugin('cachestore_mongodb');
3096 }
3097
3098 // Main savepoint reached.
25254cee 3099 upgrade_main_savepoint(true, 2023030300.02);
8ae5ebb5
AN
3100 }
3101
58fb00eb 3102 if ($oldversion < 2023030300.03) {
f58a71ba
AN
3103 // If editor_tinymce is no longer present, remove it.
3104 if (!file_exists($CFG->dirroot . '/lib/editor/tinymce/version.php')) {
3105 // Clean config.
3106 uninstall_plugin('editor', 'tinymce');
3107 $DB->delete_records('user_preferences', [
3108 'name' => 'htmleditor',
3109 'value' => 'tinymce',
3110 ]);
3111
3112 if ($editors = get_config('core', 'texteditors')) {
3113 $editors = array_flip(explode(',', $editors));
3114 unset($editors['tinymce']);
3115 set_config('texteditors', implode(',', array_flip($editors)));
3116 }
3117 }
58fb00eb 3118 upgrade_main_savepoint(true, 2023030300.03);
f58a71ba
AN
3119 }
3120
61cd980f
PH
3121 if ($oldversion < 2023031000.01) {
3122 // If logstore_legacy is no longer present, remove it.
3123 if (!file_exists($CFG->dirroot . '/admin/tool/log/store/legacy/version.php')) {
3124 unset_all_config_for_plugin('logstore_legacy');
3125 }
3126
3127 // Main savepoint reached.
3128 upgrade_main_savepoint(true, 2023031000.01);
3129 }
3130
9bf8699b
PH
3131 if ($oldversion < 2023031000.02) {
3132 // If editor_tinymce is no longer present, remove it's sub-plugins too.
3133 if (!file_exists($CFG->dirroot . '/lib/editor/tinymce/version.php')) {
3134 $DB->delete_records_select(
3135 'config_plugins',
3136 $DB->sql_like('plugin', ':plugin'),
3137 ['plugin' => $DB->sql_like_escape('tinymce_') . '%']
3138 );
3139 }
3140
3141 // Main savepoint reached.
3142 upgrade_main_savepoint(true, 2023031000.02);
3143 }
3144
a34dbbe6 3145 if ($oldversion < 2023031400.01) {
958da5b6
MJ
3146 // Define field id to be added to groups.
3147 $table = new xmldb_table('groups');
3148 $field = new xmldb_field('visibility', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'picture');
3149
3150 // Conditionally launch add field visibility.
3151 if (!$dbman->field_exists($table, $field)) {
3152 $dbman->add_field($table, $field);
3153 }
3154
3155 // Define field participation to be added to groups.
3156 $field = new xmldb_field('participation', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'visibility');
3157
3158 // Conditionally launch add field participation.
3159 if (!$dbman->field_exists($table, $field)) {
3160 $dbman->add_field($table, $field);
3161 }
3acf9672
SA
3162
3163 // Main savepoint reached.
a34dbbe6 3164 upgrade_main_savepoint(true, 2023031400.01);
958da5b6
MJ
3165 }
3166
060b63cd 3167 if ($oldversion < 2023031400.02) {
03a4abde
FR
3168
3169 // Define table xapi_states to be created.
3170 $table = new xmldb_table('xapi_states');
3171
3172 // Adding fields to table xapi_states.
3173 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
3174 $table->add_field('component', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3175 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
3176 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
3177 $table->add_field('stateid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
3178 $table->add_field('statedata', XMLDB_TYPE_TEXT, null, null, null, null, null);
3179 $table->add_field('registration', XMLDB_TYPE_CHAR, '255', null, null, null, null);
3180 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
3181 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
3182
3183 // Adding keys to table xapi_states.
3184 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
3185
3186 // Adding indexes to table xapi_states.
3187 $table->add_index('component-itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'itemid']);
3188 $table->add_index('userid', XMLDB_INDEX_NOTUNIQUE, ['userid']);
3189 $table->add_index('timemodified', XMLDB_INDEX_NOTUNIQUE, ['timemodified']);
3190
3191 // Conditionally launch create table for xapi_states.
3192 if (!$dbman->table_exists($table)) {
3193 $dbman->create_table($table);
3194 }
3195
3196 if (!isset($CFG->xapicleanupperiod)) {
3197 set_config('xapicleanupperiod', WEEKSECS * 8);
3198 }
3199
3200 // Main savepoint reached.
060b63cd 3201 upgrade_main_savepoint(true, 2023031400.02);
03a4abde
FR
3202 }
3203
1147a9fe
SA
3204 if ($oldversion < 2023032800.01) {
3205 // If mod_assignment is no longer present, remove it.
3206 if (!file_exists($CFG->dirroot . '/mod/assignment/version.php')) {
3207 uninstall_plugin('assignment', 'offline');
3208 uninstall_plugin('assignment', 'online');
3209 uninstall_plugin('assignment', 'upload');
3210 uninstall_plugin('assignment', 'uploadsingle');
3211 uninstall_plugin('mod', 'assignment');
3212 }
3213
3214 // Main savepoint reached.
3215 upgrade_main_savepoint(true, 2023032800.01);
3216 }
3217
a4cdd6d2 3218 return true;
51003653 3219}