Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
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
 *
37
 * @package   core_install
38
 * @category  upgrade
39
 * @copyright 2006 onwards Martin Dougiamas  http://dougiamas.com
40
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
41
 */
42
 
43
/**
44
 * Main upgrade tasks to be executed on Moodle version bump
45
 *
46
 * This function is automatically executed after one bump in the Moodle core
47
 * version is detected. It's in charge of performing the required tasks
48
 * to raise core from the previous version to the next one.
49
 *
50
 * It's a collection of ordered blocks of code, named "upgrade steps",
51
 * each one performing one isolated (from the rest of steps) task. Usually
52
 * tasks involve creating new DB objects or performing manipulation of the
53
 * information for cleanup/fixup purposes.
54
 *
55
 * Each upgrade step has a fixed structure, that can be summarised as follows:
56
 *
57
 * if ($oldversion < XXXXXXXXXX.XX) {
58
 *     // Explanation of the update step, linking to issue in the Tracker if necessary
59
 *     upgrade_set_timeout(XX); // Optional for big tasks
60
 *     // Code to execute goes here, usually the XMLDB Editor will
61
 *     // help you here. See {@link https://moodledev.io/general/development/tools/xmldb}.
62
 *     upgrade_main_savepoint(true, XXXXXXXXXX.XX);
63
 * }
64
 *
65
 * All plugins within Moodle (modules, blocks, reports...) support the existence of
66
 * their own upgrade.php file, using the "Frankenstyle" component name as
67
 * defined at {@link https://moodledev.io/general/development/policies/codingstyle/frankenstyle}, for example:
68
 *     - {@see xmldb_page_upgrade($oldversion)}. (modules don't require the plugintype ("mod_") to be used.
69
 *     - {@see xmldb_auth_manual_upgrade($oldversion)}.
70
 *     - {@see xmldb_workshopform_accumulative_upgrade($oldversion)}.
71
 *     - ....
72
 *
73
 * In order to keep the contents of this file reduced, it's allowed to create some helper
74
 * functions to be used here in the {@see upgradelib.php} file at the same directory. Note
75
 * that such a file must be manually included from upgrade.php, and there are some restrictions
76
 * about what can be used within it.
77
 *
78
 * For more information, take a look to the documentation available:
79
 *     - Data definition API: {@link https://moodledev.io/docs/apis/core/dml/ddl}
80
 *     - Upgrade API: {@link https://moodledev.io/docs/guides/upgrade}
81
 *
82
 * @param int $oldversion
83
 * @return bool always true
84
 */
85
function xmldb_main_upgrade($oldversion) {
86
    global $CFG, $DB;
87
 
88
    require_once($CFG->libdir . '/db/upgradelib.php'); // Core Upgrade-related functions.
89
 
90
    $dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes.
91
 
92
    // Always keep this upgrade step with version being the minimum
93
    // allowed version to upgrade from (v4.1.2 right now).
94
    if ($oldversion < 2022112802) {
95
        // Just in case somebody hacks upgrade scripts or env, we really can not continue.
96
        echo("You need to upgrade to 4.1.2 or higher first!\n");
97
        exit(1);
98
        // Note this savepoint is 100% unreachable, but needed to pass the upgrade checks.
99
        upgrade_main_savepoint(true, 2022112802);
100
    }
101
 
102
    // Automatically generated Moodle v4.1.0 release upgrade line.
103
    // Put any upgrade step following this.
104
 
105
    if ($oldversion < 2022120900.01) {
106
        // Remove any orphaned role assignment records (pointing to non-existing roles).
107
        $DB->delete_records_select('role_assignments', 'NOT EXISTS (
108
            SELECT r.id FROM {role} r WHERE r.id = {role_assignments}.roleid
109
        )');
110
 
111
        // Main savepoint reached.
112
        upgrade_main_savepoint(true, 2022120900.01);
113
    }
114
 
115
    if ($oldversion < 2022121600.01) {
116
        // Define index blocknameindex (not unique) to be added to block_instances.
117
        $table = new xmldb_table('block_instances');
118
        $index = new xmldb_index('blocknameindex', XMLDB_INDEX_NOTUNIQUE, ['blockname']);
119
 
120
        // Conditionally launch add index blocknameindex.
121
        if (!$dbman->index_exists($table, $index)) {
122
            $dbman->add_index($table, $index);
123
        }
124
        // Main savepoint reached.
125
        upgrade_main_savepoint(true, 2022121600.01);
126
    }
127
 
128
    if ($oldversion < 2023010300.00) {
129
        // The useexternalyui setting has been removed.
130
        unset_config('useexternalyui');
131
 
132
        // Main savepoint reached.
133
        upgrade_main_savepoint(true, 2023010300.00);
134
    }
135
 
136
    if ($oldversion < 2023020800.00) {
137
        // If cachestore_memcached is no longer present, remove it.
138
        if (!file_exists($CFG->dirroot . '/cache/stores/memcached/version.php')) {
139
            // Clean config.
140
            unset_all_config_for_plugin('cachestore_memcached');
141
        }
142
 
143
        // Main savepoint reached.
144
        upgrade_main_savepoint(true, 2023020800.00);
145
    }
146
 
147
    if ($oldversion < 2023021700.01) {
148
        // Define field pdfexportfont to be added to course.
149
        $table = new xmldb_table('course');
150
        $field = new xmldb_field('pdfexportfont', XMLDB_TYPE_CHAR, '50', null, false, false, null, 'showcompletionconditions');
151
 
152
        // Conditionally launch add field pdfexportfont.
153
        if (!$dbman->field_exists($table, $field)) {
154
            $dbman->add_field($table, $field);
155
        }
156
 
157
        // Main savepoint reached.
158
        upgrade_main_savepoint(true, 2023021700.01);
159
    }
160
 
161
    if ($oldversion < 2023022000.00) {
162
        // Remove grade_report_showquickfeedback, grade_report_enableajax, grade_report_showeyecons,
163
        // grade_report_showlocks, grade_report_showanalysisicon preferences for every user.
164
        $DB->delete_records('user_preferences', ['name' => 'grade_report_showquickfeedback']);
165
        $DB->delete_records('user_preferences', ['name' => 'grade_report_enableajax']);
166
        $DB->delete_records('user_preferences', ['name' => 'grade_report_showeyecons']);
167
        $DB->delete_records('user_preferences', ['name' => 'grade_report_showlocks']);
168
        $DB->delete_records('user_preferences', ['name' => 'grade_report_showanalysisicon']);
169
 
170
        // The grade_report_showquickfeedback, grade_report_enableajax, grade_report_showeyecons,
171
        // grade_report_showlocks, grade_report_showanalysisicon settings have been removed.
172
        unset_config('grade_report_showquickfeedback');
173
        unset_config('grade_report_enableajax');
174
        unset_config('grade_report_showeyecons');
175
        unset_config('grade_report_showlocks');
176
        unset_config('grade_report_showanalysisicon');
177
 
178
        // Main savepoint reached.
179
        upgrade_main_savepoint(true, 2023022000.00);
180
    }
181
 
182
    if ($oldversion < 2023030300.01) {
183
        $sql = "SELECT preset.*
184
                  FROM {adminpresets} preset
185
            INNER JOIN {adminpresets_it} it ON preset.id = it.adminpresetid
186
                 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0";
187
        // Some settings and plugins have been added/removed to the Starter and Full preset. Add them to the core presets if
188
        // they haven't been included yet.
189
        $params = ['name' => get_string('starterpreset', 'core_adminpresets'), 'iscore' => 1];
190
        $starterpreset = $DB->get_record('adminpresets', $params);
191
        if (!$starterpreset) {
192
            // Starter admin preset might have been created using the English name.
193
            $name = get_string_manager()->get_string('starterpreset', 'core_adminpresets', null, 'en');
194
            $params['name'] = $name;
195
            $starterpreset = $DB->get_record('adminpresets', $params);
196
        }
197
        if (!$starterpreset) {
198
            // We tried, but we didn't find starter by name. Let's find a core preset that sets 'usecomments' setting to 0.
199
            $params = ['name' => 'usecomments', 'value' => '0'];
200
            $starterpreset = $DB->get_record_sql($sql, $params);
201
        }
202
 
203
        $params = ['name' => get_string('fullpreset', 'core_adminpresets')];
204
        $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params);
205
        if (!$fullpreset) {
206
            // Full admin preset might have been created using the English name.
207
            $name = get_string_manager()->get_string('fullpreset', 'core_adminpresets', null, 'en');
208
            $params['name'] = $name;
209
            $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params);
210
        }
211
        if (!$fullpreset) {
212
            // We tried, but we didn't find full by name. Let's find a core preset that sets 'usecomments' setting to 1.
213
            $params = ['name' => 'usecomments', 'value' => '1'];
214
            $fullpreset = $DB->get_record_sql($sql, $params);
215
        }
216
 
217
        $settings = [
218
            // Settings. Set Activity chooser tabs to "Starred, Recommended, All"(5) for Starter and back it to default(3) for Full.
219
            [
220
                'presetid' => $starterpreset->id,
221
                'plugin' => 'none',
222
                'name' => 'activitychoosertabmode',
223
                'value' => '4',
224
            ],
225
            [
226
                'presetid' => $fullpreset->id,
227
                'plugin' => 'none',
228
                'name' => 'activitychoosertabmode',
229
                'value' => '3',
230
            ],
231
        ];
232
        foreach ($settings as $notused => $setting) {
233
            $params = ['adminpresetid' => $setting['presetid'], 'plugin' => $setting['plugin'], 'name' => $setting['name']];
234
            if (!$record = $DB->get_record('adminpresets_it', $params)) {
235
                $record = new \stdClass();
236
                $record->adminpresetid = $setting['presetid'];
237
                $record->plugin = $setting['plugin'];
238
                $record->name = $setting['name'];
239
                $record->value = $setting['value'];
240
                $DB->insert_record('adminpresets_it', $record);
241
            } else {
242
                $record->value = $setting['value'];
243
                $DB->update_record('adminpresets_it', $record);
244
            }
245
        }
246
 
247
        // Main savepoint reached.
248
        upgrade_main_savepoint(true, 2023030300.01);
249
    }
250
 
251
    if ($oldversion < 2023030300.02) {
252
        // If cachestore_mongodb is no longer present, remove it.
253
        if (!file_exists($CFG->dirroot . '/cache/stores/mongodb/version.php')) {
254
            // Clean config.
255
            unset_all_config_for_plugin('cachestore_mongodb');
256
        }
257
 
258
        // Main savepoint reached.
259
        upgrade_main_savepoint(true, 2023030300.02);
260
    }
261
 
262
    if ($oldversion < 2023030300.03) {
263
        // If editor_tinymce is no longer present, remove it.
264
        if (!file_exists($CFG->dirroot . '/lib/editor/tinymce/version.php')) {
265
            // Clean config.
266
            uninstall_plugin('editor', 'tinymce');
267
            $DB->delete_records('user_preferences', [
268
                'name' => 'htmleditor',
269
                'value' => 'tinymce',
270
            ]);
271
 
272
            if ($editors = get_config('core', 'texteditors')) {
273
                $editors = array_flip(explode(',', $editors));
274
                unset($editors['tinymce']);
275
                set_config('texteditors', implode(',', array_flip($editors)));
276
            }
277
        }
278
        upgrade_main_savepoint(true, 2023030300.03);
279
    }
280
 
281
    if ($oldversion < 2023031000.02) {
282
        // If editor_tinymce is no longer present, remove it's sub-plugins too.
283
        if (!file_exists($CFG->dirroot . '/lib/editor/tinymce/version.php')) {
284
            $DB->delete_records_select(
285
                'config_plugins',
286
                $DB->sql_like('plugin', ':plugin'),
287
                ['plugin' => $DB->sql_like_escape('tinymce_') . '%']
288
            );
289
        }
290
 
291
        // Main savepoint reached.
292
        upgrade_main_savepoint(true, 2023031000.02);
293
    }
294
 
295
    if ($oldversion < 2023031400.01) {
296
        // Define field id to be added to groups.
297
        $table = new xmldb_table('groups');
298
        $field = new xmldb_field('visibility', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'picture');
299
 
300
        // Conditionally launch add field visibility.
301
        if (!$dbman->field_exists($table, $field)) {
302
            $dbman->add_field($table, $field);
303
        }
304
 
305
        // Define field participation to be added to groups.
306
        $field = new xmldb_field('participation', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'visibility');
307
 
308
        // Conditionally launch add field participation.
309
        if (!$dbman->field_exists($table, $field)) {
310
            $dbman->add_field($table, $field);
311
        }
312
 
313
        // Main savepoint reached.
314
        upgrade_main_savepoint(true, 2023031400.01);
315
    }
316
 
317
    if ($oldversion < 2023031400.02) {
318
        // Define table xapi_states to be created.
319
        $table = new xmldb_table('xapi_states');
320
 
321
        // Adding fields to table xapi_states.
322
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
323
        $table->add_field('component', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
324
        $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
325
        $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
326
        $table->add_field('stateid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
327
        $table->add_field('statedata', XMLDB_TYPE_TEXT, null, null, null, null, null);
328
        $table->add_field('registration', XMLDB_TYPE_CHAR, '255', null, null, null, null);
329
        $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
330
        $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
331
 
332
        // Adding keys to table xapi_states.
333
        $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
334
 
335
        // Adding indexes to table xapi_states.
336
        $table->add_index('component-itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'itemid']);
337
        $table->add_index('userid', XMLDB_INDEX_NOTUNIQUE, ['userid']);
338
        $table->add_index('timemodified', XMLDB_INDEX_NOTUNIQUE, ['timemodified']);
339
 
340
        // Conditionally launch create table for xapi_states.
341
        if (!$dbman->table_exists($table)) {
342
            $dbman->create_table($table);
343
        }
344
 
345
        if (!isset($CFG->xapicleanupperiod)) {
346
            set_config('xapicleanupperiod', WEEKSECS * 8);
347
        }
348
 
349
        // Main savepoint reached.
350
        upgrade_main_savepoint(true, 2023031400.02);
351
    }
352
 
353
    if ($oldversion < 2023040600.01) {
354
        // If logstore_legacy is no longer present, remove it.
355
        if (!file_exists($CFG->dirroot . '/admin/tool/log/store/legacy/version.php')) {
356
            uninstall_plugin('logstore', 'legacy');
357
        }
358
 
359
        // Main savepoint reached.
360
        upgrade_main_savepoint(true, 2023040600.01);
361
    }
362
 
363
    if ($oldversion < 2023041100.00) {
364
        // Add public key field to user_devices table.
365
        $table = new xmldb_table('user_devices');
366
        $field = new xmldb_field('publickey', XMLDB_TYPE_TEXT, null, null, null, null, null, 'uuid');
367
 
368
        if (!$dbman->field_exists($table, $field)) {
369
            $dbman->add_field($table, $field);
370
        }
371
 
372
        // Main savepoint reached.
373
        upgrade_main_savepoint(true, 2023041100.00);
374
    }
375
 
376
    if ($oldversion < 2023042000.00) {
377
        // If mod_assignment is no longer present, remove it.
378
        if (!file_exists($CFG->dirroot . '/mod/assignment/version.php')) {
379
            // Delete all mod_assignment grade_grades orphaned data.
380
            $DB->delete_records_select(
381
                'grade_grades',
382
                "itemid IN (SELECT id FROM {grade_items} WHERE itemtype = 'mod' AND itemmodule = 'assignment')"
383
            );
384
 
385
            // Delete all mod_assignment grade_grades_history orphaned data.
386
            $DB->delete_records('grade_grades_history', ['source' => 'mod/assignment']);
387
 
388
            // Delete all mod_assignment grade_items orphaned data.
389
            $DB->delete_records('grade_items', ['itemtype' => 'mod', 'itemmodule' => 'assignment']);
390
 
391
            // Delete all mod_assignment grade_items_history orphaned data.
392
            $DB->delete_records('grade_items_history', ['itemtype' => 'mod', 'itemmodule' => 'assignment']);
393
 
394
            // Delete core mod_assignment subplugins.
395
            uninstall_plugin('assignment', 'offline');
396
            uninstall_plugin('assignment', 'online');
397
            uninstall_plugin('assignment', 'upload');
398
            uninstall_plugin('assignment', 'uploadsingle');
399
 
400
            // Delete other mod_assignment subplugins.
401
            $pluginnamelike = $DB->sql_like('plugin', ':pluginname');
402
            $subplugins = $DB->get_fieldset_select('config_plugins', 'plugin', "$pluginnamelike AND name = :name", [
403
                'pluginname' => $DB->sql_like_escape('assignment_') . '%',
404
                'name' => 'version',
405
            ]);
406
            foreach ($subplugins as $subplugin) {
407
                [$plugin, $subpluginname] = explode('_', $subplugin, 2);
408
                uninstall_plugin($plugin, $subpluginname);
409
            }
410
 
411
            // Delete mod_assignment.
412
            uninstall_plugin('mod', 'assignment');
413
        }
414
 
415
        // Main savepoint reached.
416
        upgrade_main_savepoint(true, 2023042000.00);
417
    }
418
 
419
    // Automatically generated Moodle v4.2.0 release upgrade line.
420
    // Put any upgrade step following this.
421
 
422
    if ($oldversion < 2023051500.00) {
423
        // Define communication table.
424
        $table = new xmldb_table('communication');
425
 
426
        // Adding fields to table communication.
427
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE);
428
        $table->add_field('instanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
429
        $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'instanceid');
430
        $table->add_field('instancetype', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'component');
431
        $table->add_field('provider', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'instancerype');
432
        $table->add_field('roomname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'provider');
433
        $table->add_field('avatarfilename', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'roomname');
434
        $table->add_field('active', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 1, 'avatarfilename');
435
 
436
        // Add key.
437
        $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
438
 
439
        // Conditionally launch create table for communication.
440
        if (!$dbman->table_exists($table)) {
441
            $dbman->create_table($table);
442
        }
443
 
444
        // Define communication user table.
445
        $table = new xmldb_table('communication_user');
446
 
447
        // Adding fields to table communication.
448
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE);
449
        $table->add_field('commid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id');
450
        $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'commid');
451
        $table->add_field('synced', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'userid');
452
        $table->add_field('deleted', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'synced');
453
 
454
        // Add keys.
455
        $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
456
        $table->add_key('commid', XMLDB_KEY_FOREIGN, ['commid'], 'communication', ['id']);
457
        $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']);
458
 
459
        // Conditionally launch create table for communication.
460
        if (!$dbman->table_exists($table)) {
461
            $dbman->create_table($table);
462
        }
463
 
464
        // Main savepoint reached.
465
        upgrade_main_savepoint(true, 2023051500.00);
466
    }
467
 
468
    if ($oldversion < 2023062200.00) {
469
        // Remove device specific fields for themes from config table.
470
        unset_config('thememobile');
471
        unset_config('themelegacy');
472
        unset_config('themetablet');
473
 
474
        upgrade_main_savepoint(true, 2023062200.00);
475
    }
476
 
477
    if ($oldversion < 2023062700.01) {
478
        // Define field name to be added to external_tokens.
479
        $table = new xmldb_table('external_tokens');
480
        $field = new xmldb_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'lastaccess');
481
        // Conditionally launch add field name.
482
        if (!$dbman->field_exists($table, $field)) {
483
            $dbman->add_field($table, $field);
484
        }
485
        // Update the old external tokens.
486
        $sql = 'UPDATE {external_tokens}
487
                   SET name = ' . $DB->sql_concat(
488
                       // We only need the prefix, so leave the third param with an empty string.
489
                        "'" . get_string('tokennameprefix', 'webservice', '') . "'",
490
                        "id"
491
                    );
492
        $DB->execute($sql);
493
        // Main savepoint reached.
494
        upgrade_main_savepoint(true, 2023062700.01);
495
    }
496
 
497
    if ($oldversion < 2023062900.01) {
498
        // Define field avatarsynced to be added to communication.
499
        $table = new xmldb_table('communication');
500
        $field = new xmldb_field('avatarsynced', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'active');
501
 
502
        // Conditionally launch add field avatarsynced.
503
        if (!$dbman->field_exists($table, $field)) {
504
            $dbman->add_field($table, $field);
505
        }
506
 
507
        // Main savepoint reached.
508
        upgrade_main_savepoint(true, 2023062900.01);
509
    }
510
 
511
    if ($oldversion < 2023080100.00) {
512
        // Upgrade yaml mime type for existing yaml and yml files.
513
        $filetypes = [
514
            '%.yaml' => 'application/yaml',
515
            '%.yml' => 'application/yaml,',
516
        ];
517
 
518
        $select = $DB->sql_like('filename', '?', false);
519
        foreach ($filetypes as $extension => $mimetype) {
520
            $DB->set_field_select(
521
                'files',
522
                'mimetype',
523
                $mimetype,
524
                $select,
525
                [$extension]
526
            );
527
        }
528
 
529
        // Main savepoint reached.
530
        upgrade_main_savepoint(true, 2023080100.00);
531
    }
532
 
533
    if ($oldversion < 2023081500.00) {
534
        upgrade_core_licenses();
535
        upgrade_main_savepoint(true, 2023081500.00);
536
    }
537
 
538
    if ($oldversion < 2023081800.01) {
539
        // Remove enabledevicedetection and devicedetectregex from config table.
540
        unset_config('enabledevicedetection');
541
        unset_config('devicedetectregex');
542
        // Main savepoint reached.
543
        upgrade_main_savepoint(true, 2023081800.01);
544
    }
545
 
546
    if ($oldversion < 2023082200.01) {
547
        // Some MIME icons have been removed and replaced with existing icons. They need to be upgraded for custom MIME types.
548
        $replacedicons = [
549
            'avi' => 'video',
550
            'base' => 'database',
551
            'bmp' => 'image',
552
            'html' => 'markup',
553
            'jpeg' => 'image',
554
            'mov' => 'video',
555
            'mp3' => 'audio',
556
            'mpeg' => 'video',
557
            'png' => 'image',
558
            'quicktime' => 'video',
559
            'tiff' => 'image',
560
            'wav' => 'audio',
561
            'wmv' => 'video',
562
        ];
563
 
564
        $custom = [];
565
        if (!empty($CFG->customfiletypes)) {
566
            if (array_key_exists('customfiletypes', $CFG->config_php_settings)) {
567
                // It's set in config.php, so the MIME icons can't be upgraded automatically.
568
                echo("\nYou need to manually check customfiletypes in config.php because some MIME icons have been removed!\n");
569
            } else {
570
                // It's a JSON string in the config table.
571
                $custom = json_decode($CFG->customfiletypes);
572
            }
573
        }
574
 
575
        $changed = false;
576
        foreach ($custom as $customentry) {
577
            if (!empty($customentry->icon) && array_key_exists($customentry->icon, $replacedicons)) {
578
                $customentry->icon = $replacedicons[$customentry->icon];
579
                $changed = true;
580
            }
581
        }
582
 
583
        if ($changed) {
584
            // Save the new customfiletypes.
585
            set_config('customfiletypes', json_encode($custom));
586
        }
587
 
588
        // Main savepoint reached.
589
        upgrade_main_savepoint(true, 2023082200.01);
590
    }
591
 
592
    if ($oldversion < 2023082200.02) {
593
        // Some MIME icons have been removed. They need to be replaced to 'unknown' for custom MIME types.
594
        $removedicons = array_flip([
595
            'clip-353',
596
            'edit',
597
            'env',
598
            'explore',
599
            'folder-open',
600
            'help',
601
            'move',
602
            'parent',
603
        ]);
604
 
605
        $custom = [];
606
        if (!empty($CFG->customfiletypes)) {
607
            if (array_key_exists('customfiletypes', $CFG->config_php_settings)) {
608
                // It's set in config.php, so the MIME icons can't be upgraded automatically.
609
                echo("\nYou need to manually check customfiletypes in config.php because some MIME icons have been removed!\n");
610
            } else {
611
                // It's a JSON string in the config table.
612
                $custom = json_decode($CFG->customfiletypes);
613
            }
614
        }
615
 
616
        $changed = false;
617
        foreach ($custom as $customentry) {
618
            if (!empty($customentry->icon) && array_key_exists($customentry->icon, $removedicons)) {
619
                // The icon has been removed, so set it to unknown.
620
                $customentry->icon = 'unknown';
621
                $changed = true;
622
            }
623
        }
624
 
625
        if ($changed) {
626
            // Save the new customfiletypes.
627
            set_config('customfiletypes', json_encode($custom));
628
        }
629
 
630
        // Main savepoint reached.
631
        upgrade_main_savepoint(true, 2023082200.02);
632
    }
633
 
634
    if ($oldversion < 2023082200.04) {
635
        // Remove any non-unique filters/conditions.
636
        $duplicates = $DB->get_records_sql("
637
            SELECT MIN(id) AS id, reportid, uniqueidentifier, iscondition
638
              FROM {reportbuilder_filter}
639
          GROUP BY reportid, uniqueidentifier, iscondition
640
            HAVING COUNT(*) > 1");
641
 
642
        foreach ($duplicates as $duplicate) {
643
            $DB->delete_records_select(
644
                'reportbuilder_filter',
645
                'id <> :id AND reportid = :reportid AND uniqueidentifier = :uniqueidentifier AND iscondition = :iscondition',
646
                (array) $duplicate
647
            );
648
        }
649
 
650
        // Define index report-filter (unique) to be added to reportbuilder_filter.
651
        $table = new xmldb_table('reportbuilder_filter');
652
        $index = new xmldb_index('report-filter', XMLDB_INDEX_UNIQUE, ['reportid', 'uniqueidentifier', 'iscondition']);
653
 
654
        // Conditionally launch add index report-filter.
655
        if (!$dbman->index_exists($table, $index)) {
656
            $dbman->add_index($table, $index);
657
        }
658
 
659
        // Main savepoint reached.
660
        upgrade_main_savepoint(true, 2023082200.04);
661
    }
662
 
663
    if ($oldversion < 2023082600.02) {
664
        // Get all the ids of users who still have md5 hashed passwords.
665
        if ($DB->sql_regex_supported()) {
666
            // If the database supports regex, we can add an exact check for md5.
667
            $condition = 'password ' . $DB->sql_regex() . ' :pattern';
668
            $params = ['pattern' => "^[a-fA-F0-9]{32}$"];
669
        } else {
670
            // Otherwise, we need to use a NOT LIKE condition and rule out bcrypt.
671
            $condition = $DB->sql_like('password', ':pattern', true, false, true);
672
            $params = ['pattern' => '$2y$%'];
673
        }
674
 
675
        // Regardless of database regex support we check the hash length which should be enough.
676
        // But extra regex or like matching makes sure.
677
        $sql = "SELECT id FROM {user} WHERE " . $DB->sql_length('password') . " = 32 AND $condition";
678
        $userids = $DB->get_fieldset_sql($sql, $params);
679
 
680
        // Update the password for each user with a new SHA-512 hash.
681
        // Users won't know this password, but they can reset it. This is a security measure,
682
        // in case the database is compromised or the hash has been leaked elsewhere.
683
        foreach ($userids as $userid) {
684
            $password = base64_encode(random_bytes(24)); // Generate a new password for the user.
685
 
686
            $user = new \stdClass();
687
            $user->id = $userid;
688
            $user->password = hash_internal_user_password($password);
689
            $DB->update_record('user', $user, true);
690
        }
691
 
692
        // Main savepoint reached.
693
        upgrade_main_savepoint(true, 2023082600.02);
694
    }
695
 
696
    if ($oldversion < 2023082600.03) {
697
        // The previous default configuration had a typo, check for its presence and correct if necessary.
698
        $sensiblesettings = get_config('adminpresets', 'sensiblesettings');
699
        if (strpos($sensiblesettings, 'smtppass@none') !== false) {
700
            $newsensiblesettings = str_replace('smtppass@none', 'smtppass@@none', $sensiblesettings);
701
            set_config('sensiblesettings', $newsensiblesettings, 'adminpresets');
702
        }
703
 
704
        // Main savepoint reached.
705
        upgrade_main_savepoint(true, 2023082600.03);
706
    }
707
 
708
    if ($oldversion < 2023082600.05) {
709
        unset_config('completiondefault');
710
 
711
        // Main savepoint reached.
712
        upgrade_main_savepoint(true, 2023082600.05);
713
    }
714
 
715
    if ($oldversion < 2023090100.00) {
716
        // Upgrade MIME type for existing PSD files.
717
        $DB->set_field_select(
718
            'files',
719
            'mimetype',
720
            'image/vnd.adobe.photoshop',
721
            $DB->sql_like('filename', '?', false),
722
            ['%.psd']
723
        );
724
 
725
        // Main savepoint reached.
726
        upgrade_main_savepoint(true, 2023090100.00);
727
    }
728
 
729
    if ($oldversion < 2023090200.01) {
730
        // Define table moodlenet_share_progress to be created.
731
        $table = new xmldb_table('moodlenet_share_progress');
732
 
733
        // Adding fields to table moodlenet_share_progress.
734
        $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
735
        $table->add_field('type', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, null);
736
        $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
737
        $table->add_field('cmid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
738
        $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
739
        $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
740
        $table->add_field('resourceurl', XMLDB_TYPE_CHAR, '255', null, null, null, null);
741
        $table->add_field('status', XMLDB_TYPE_INTEGER, '2', null, null, null, null);
742
 
743
        // Adding keys to table moodlenet_share_progress.
744
        $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
745
 
746
        // Conditionally launch create table for moodlenet_share_progress.
747
        if (!$dbman->table_exists($table)) {
748
            $dbman->create_table($table);
749
        }
750
 
751
        // Main savepoint reached.
752
        upgrade_main_savepoint(true, 2023090200.01);
753
    }
754
 
755
    if ($oldversion < 2023091300.03) {
756
        // Delete all the searchanywhere prefs in user_preferences table.
757
        $DB->delete_records('user_preferences', ['name' => 'userselector_searchanywhere']);
758
        // Main savepoint reached.
759
        upgrade_main_savepoint(true, 2023091300.03);
760
    }
761
 
762
    if ($oldversion < 2023100400.01) {
763
        // Delete datakey with datavalue -1.
764
        $DB->delete_records('messageinbound_datakeys', ['datavalue' => '-1']);
765
        // Main savepoint reached.
766
        upgrade_main_savepoint(true, 2023100400.01);
767
    }
768
 
769
    if ($oldversion < 2023100400.03) {
770
        // Define field id to be added to communication.
771
        $table = new xmldb_table('communication');
772
 
773
        // Add the field and allow it to be nullable.
774
        // We need to backfill data before setting it to NOT NULL.
775
        $field = new xmldb_field(
776
            name: 'contextid',
777
            type: XMLDB_TYPE_INTEGER,
778
            precision: '10',
779
            notnull: null,
780
            previous: 'id',
781
        );
782
 
783
        // Conditionally launch add field id.
784
        if (!$dbman->field_exists($table, $field)) {
785
            $dbman->add_field($table, $field);
786
        }
787
 
788
        // Fill the existing data.
789
        $sql = <<<EOF
790
                    SELECT comm.id, c.id AS contextid
791
                      FROM {communication} comm
792
                INNER JOIN {context} c ON c.instanceid = comm.instanceid AND c.contextlevel = :contextcourse
793
                     WHERE comm.contextid IS NULL
794
                       AND comm.instancetype = :instancetype
795
        EOF;
796
        $rs = $DB->get_recordset_sql(
797
            sql: $sql,
798
            params: [
799
                'contextcourse' => CONTEXT_COURSE,
800
                'instancetype' => 'coursecommunication',
801
            ],
802
        );
803
        foreach ($rs as $comm) {
804
            $DB->set_field(
805
                table: 'communication',
806
                newfield: 'contextid',
807
                newvalue: $comm->contextid,
808
                conditions: [
809
                    'id' => $comm->id,
810
                ],
811
            );
812
        }
813
        $rs->close();
814
 
815
        $systemcontext = \core\context\system::instance();
816
        $DB->set_field_select(
817
            table: 'communication',
818
            newfield: 'contextid',
819
            newvalue: $systemcontext->id,
820
            select: 'contextid IS NULL',
821
        );
822
 
823
        // Now make it NOTNULL.
824
        $field = new xmldb_field(
825
            name: 'contextid',
826
            type: XMLDB_TYPE_INTEGER,
827
            precision: '10',
828
            notnull:  XMLDB_NOTNULL,
829
        );
830
        $dbman->change_field_notnull($table, $field);
831
 
832
        // Add the contextid constraint.
833
        $key = new xmldb_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']);
834
        $dbman->add_key($table, $key);
835
 
836
        // Main savepoint reached.
837
        upgrade_main_savepoint(true, 2023100400.03);
838
    }
839
 
840
    // Automatically generated Moodle v4.3.0 release upgrade line.
841
    // Put any upgrade step following this.
842
 
843
    if ($oldversion < 2023110900.00) {
844
        // Reorder the editors to make Tiny the default for all upgrades.
845
        $editors = [];
846
        array_push($editors, 'tiny');
847
        $list = explode(',', $CFG->texteditors);
848
        foreach ($list as $editor) {
849
            if ($editor != 'tiny') {
850
                array_push($editors, $editor);
851
            }
852
        }
853
        set_config('texteditors', implode(',', $editors));
854
 
855
        // Main savepoint reached.
856
        upgrade_main_savepoint(true, 2023110900.00);
857
    }
858
 
859
    if ($oldversion < 2023120100.01) {
860
        // The $CFG->linkcoursesections setting has been removed because it's not required anymore.
861
        // From now, sections will be always linked because a new page, section.php, has been created to display a single section.
862
        unset_config('linkcoursesections');
863
 
864
        upgrade_main_savepoint(true, 2023120100.01);
865
    }
866
 
867
    if ($oldversion < 2023121800.02) {
868
        // Define field attemptsavailable to be added to task_adhoc.
869
        $table = new xmldb_table('task_adhoc');
870
        $field = new xmldb_field(
871
            name: 'attemptsavailable',
872
            type: XMLDB_TYPE_INTEGER,
873
            precision: '2',
874
            unsigned: null,
875
            notnull: null,
876
            sequence: null,
877
            default: null,
878
            previous: 'pid',
879
        );
880
 
881
        // Conditionally launch add field attemptsavailable.
882
        if (!$dbman->field_exists($table, $field)) {
883
            $dbman->add_field($table, $field);
884
        }
885
 
886
        // Set attemptsavailable to 0 for the tasks that have not been run before.
887
        // Set attemptsavailable to 1 for the tasks that have been run and failed before.
888
        $DB->execute('
889
            UPDATE {task_adhoc}
890
               SET attemptsavailable = CASE
891
                                            WHEN faildelay = 0 THEN 1
892
                                            WHEN faildelay > 0 THEN 0
893
                                       END
894
        ');
895
 
896
        // Main savepoint reached.
897
        upgrade_main_savepoint(true, 2023121800.02);
898
    }
899
 
900
    if ($oldversion < 2023122100.01) {
901
 
902
        // Define field component to be added to course_sections.
903
        $table = new xmldb_table('course_sections');
904
        $field = new xmldb_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'availability');
905
 
906
        // Conditionally launch add field component.
907
        if (!$dbman->field_exists($table, $field)) {
908
            $dbman->add_field($table, $field);
909
        }
910
 
911
        // Define field itemid to be added to course_sections.
912
        $field = new xmldb_field('itemid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'component');
913
 
914
        // Conditionally launch add field itemid.
915
        if (!$dbman->field_exists($table, $field)) {
916
            $dbman->add_field($table, $field);
917
        }
918
 
919
        // Main savepoint reached.
920
        upgrade_main_savepoint(true, 2023122100.01);
921
    }
922
 
923
    if ($oldversion < 2023122100.02) {
924
        $sqllike = $DB->sql_like('filtercondition', '?');
925
        $params[] = '%includesubcategories%';
926
 
927
        $sql = "SELECT qsr.* FROM {question_set_references} qsr WHERE $sqllike";
928
        $results = $DB->get_recordset_sql($sql, $params);
929
        foreach ($results as $result) {
930
            $filtercondition = json_decode($result->filtercondition);
931
            if (isset($filtercondition->filter->category->includesubcategories)) {
932
                $filtercondition->filter->category->filteroptions =
933
                    ['includesubcategories' => $filtercondition->filter->category->includesubcategories];
934
                unset($filtercondition->filter->category->includesubcategories);
935
                $result->filtercondition = json_encode($filtercondition);
936
                $DB->update_record('question_set_references', $result);
937
            }
938
        }
939
        $results->close();
940
 
941
        upgrade_main_savepoint(true, 2023122100.02);
942
    }
943
 
944
    if ($oldversion < 2024010400.01) {
945
 
946
        // Define index timecreated (not unique) to be added to notifications.
947
        $table = new xmldb_table('notifications');
948
        $createdindex = new xmldb_index('timecreated', XMLDB_INDEX_NOTUNIQUE, ['timecreated']);
949
 
950
        // Conditionally launch add index timecreated.
951
        if (!$dbman->index_exists($table, $createdindex)) {
952
            $dbman->add_index($table, $createdindex);
953
        }
954
 
955
        // Define index timeread (not unique) to be added to notifications.
956
        $readindex = new xmldb_index('timeread', XMLDB_INDEX_NOTUNIQUE, ['timeread']);
957
 
958
        // Conditionally launch add index timeread.
959
        if (!$dbman->index_exists($table, $readindex)) {
960
            $dbman->add_index($table, $readindex);
961
        }
962
 
963
        // Main savepoint reached.
964
        upgrade_main_savepoint(true, 2024010400.01);
965
    }
966
 
967
    if ($oldversion < 2024012300.00) {
968
 
969
        // Define field valuetrust to be added to customfield_data.
970
        $table = new xmldb_table('customfield_data');
971
        $field = new xmldb_field('valuetrust', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'valueformat');
972
 
973
        // Conditionally launch add field valuetrust.
974
        if (!$dbman->field_exists($table, $field)) {
975
            $dbman->add_field($table, $field);
976
        }
977
 
978
        // Main savepoint reached.
979
        upgrade_main_savepoint(true, 2024012300.00);
980
    }
981
 
982
    if ($oldversion < 2024020200.01) {
983
        // If h5plib_v124 is no longer present, remove it.
984
        if (!file_exists($CFG->dirroot . '/h5p/h5plib/v124/version.php')) {
985
            // Clean config.
986
            uninstall_plugin('h5plib', 'v124');
987
        }
988
 
989
        // If h5plib_v126 is present, set it as the default one.
990
        if (file_exists($CFG->dirroot . '/h5p/h5plib/v126/version.php')) {
991
            set_config('h5plibraryhandler', 'h5plib_v126');
992
        }
993
 
994
        upgrade_main_savepoint(true, 2024020200.01);
995
    }
996
 
997
    if ($oldversion < 2024021500.01) {
998
        // Change default course formats order for sites never changed the default order.
999
        if (!get_config('core', 'format_plugins_sortorder')) {
1000
            set_config('format_plugins_sortorder', 'topics,weeks,singleactivity,social');
1001
        }
1002
 
1003
        // Main savepoint reached.
1004
        upgrade_main_savepoint(true, 2024021500.01);
1005
    }
1006
 
1007
    if ($oldversion < 2024021500.02) {
1008
        // A [name => url] map of new OIDC endpoints to be updated/created.
1009
        $endpointuris = [
1010
            'authorization_endpoint' => 'https://clever.com/oauth/authorize',
1011
            'token_endpoint' => 'https://clever.com/oauth/tokens',
1012
            'userinfo_endpoint' => 'https://api.clever.com/userinfo',
1013
            'jwks_uri' => 'https://clever.com/oauth/certs',
1014
        ];
1015
 
1016
        // A [internalfield => externalfield] map of new OIDC-based user field mappings to be updated/created.
1017
        $userfieldmappings = [
1018
            'idnumber' => 'sub',
1019
            'firstname' => 'given_name',
1020
            'lastname' => 'family_name',
1021
            'email' => 'email',
1022
        ];
1023
 
1024
        $admin = get_admin();
1025
        $adminid = $admin ? $admin->id : '0';
1026
 
1027
        $cleverservices = $DB->get_records('oauth2_issuer', ['servicetype' => 'clever']);
1028
        foreach ($cleverservices as $cleverservice) {
1029
            $time = time();
1030
 
1031
            // Insert/update the new endpoints.
1032
            foreach ($endpointuris as $endpointname => $endpointuri) {
1033
                $endpoint = ['issuerid' => $cleverservice->id, 'name' => $endpointname];
1034
                $endpointid = $DB->get_field('oauth2_endpoint', 'id', $endpoint);
1035
 
1036
                if ($endpointid) {
1037
                    $endpoint = array_merge($endpoint, [
1038
                        'id' => $endpointid,
1039
                        'url' => $endpointuri,
1040
                        'timemodified' => $time,
1041
                        'usermodified' => $adminid,
1042
                    ]);
1043
                    $DB->update_record('oauth2_endpoint', $endpoint);
1044
                } else {
1045
                    $endpoint = array_merge($endpoint, [
1046
                        'url' => $endpointuri,
1047
                        'timecreated' => $time,
1048
                        'timemodified' => $time,
1049
                        'usermodified' => $adminid,
1050
                    ]);
1051
                    $DB->insert_record('oauth2_endpoint', $endpoint);
1052
                }
1053
            }
1054
 
1055
            // Insert/update new user field mappings.
1056
            foreach ($userfieldmappings as $internalfieldname => $externalfieldname) {
1057
                $fieldmap = ['issuerid' => $cleverservice->id, 'internalfield' => $internalfieldname];
1058
                $fieldmapid = $DB->get_field('oauth2_user_field_mapping', 'id', $fieldmap);
1059
 
1060
                if ($fieldmapid) {
1061
                    $fieldmap = array_merge($fieldmap, [
1062
                        'id' => $fieldmapid,
1063
                        'externalfield' => $externalfieldname,
1064
                        'timemodified' => $time,
1065
                        'usermodified' => $adminid,
1066
                    ]);
1067
                    $DB->update_record('oauth2_user_field_mapping', $fieldmap);
1068
                } else {
1069
                    $fieldmap = array_merge($fieldmap, [
1070
                        'externalfield' => $externalfieldname,
1071
                        'timecreated' => $time,
1072
                        'timemodified' => $time,
1073
                        'usermodified' => $adminid,
1074
                    ]);
1075
                    $DB->insert_record('oauth2_user_field_mapping', $fieldmap);
1076
                }
1077
            }
1078
 
1079
            // Update the baseurl for the issuer.
1080
            $cleverservice->baseurl = 'https://clever.com';
1081
            $cleverservice->timemodified = $time;
1082
            $cleverservice->usermodified = $adminid;
1083
            $DB->update_record('oauth2_issuer', $cleverservice);
1084
        }
1085
 
1086
        upgrade_main_savepoint(true, 2024021500.02);
1087
    }
1088
 
1089
    if ($oldversion < 2024022300.02) {
1090
        // Removed advanced grade item settings.
1091
        unset_config('grade_item_advanced');
1092
 
1093
        upgrade_main_savepoint(true, 2024022300.02);
1094
    }
1095
 
1096
    if ($oldversion < 2024030500.01) {
1097
 
1098
        // Define field firststartingtime to be added to task_adhoc.
1099
        $table = new xmldb_table('task_adhoc');
1100
        $field = new xmldb_field('firststartingtime', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'attemptsavailable');
1101
 
1102
        // Conditionally launch add field firststartingtime.
1103
        if (!$dbman->field_exists($table, $field)) {
1104
            $dbman->add_field($table, $field);
1105
            // Main savepoint reached.
1106
            upgrade_main_savepoint(true, 2024030500.01);
1107
        }
1108
 
1109
    }
1110
 
1111
    if ($oldversion < 2024030500.02) {
1112
 
1113
        // Get all "select" custom field shortnames.
1114
        $fieldshortnames = $DB->get_fieldset('customfield_field', 'shortname', ['type' => 'select']);
1115
 
1116
        // Ensure any used in custom reports columns are not using integer type aggregation.
1117
        foreach ($fieldshortnames as $fieldshortname) {
1118
            $DB->execute("
1119
                UPDATE {reportbuilder_column}
1120
                   SET aggregation = NULL
1121
                 WHERE " . $DB->sql_like('uniqueidentifier', ':uniqueidentifier', false) . "
1122
                   AND aggregation IN ('avg', 'max', 'min', 'sum')
1123
            ", [
1124
                'uniqueidentifier' => '%' . $DB->sql_like_escape(":customfield_{$fieldshortname}"),
1125
            ]);
1126
        }
1127
 
1128
        // Main savepoint reached.
1129
        upgrade_main_savepoint(true, 2024030500.02);
1130
    }
1131
 
1132
    if ($oldversion < 2024032600.01) {
1133
 
1134
        // Changing precision of field attemptsavailable on table task_adhoc to (2).
1135
        $table = new xmldb_table('task_adhoc');
1136
        $field = new xmldb_field('attemptsavailable', XMLDB_TYPE_INTEGER, '2', null, null, null, null, 'pid');
1137
 
1138
        // Launch change of precision for field.
1139
        if (!$dbman->field_exists($table, $field)) {
1140
            $dbman->change_field_precision($table, $field);
1141
        }
1142
 
1143
        // Main savepoint reached.
1144
        upgrade_main_savepoint(true, 2024032600.01);
1145
    }
1146
 
1147
    if ($oldversion < 2024041200.00) {
1148
        // Define field blocking to be dropped from task_adhoc.
1149
        $table = new xmldb_table('task_adhoc');
1150
        $field = new xmldb_field('blocking');
1151
 
1152
        // Conditionally launch drop field blocking.
1153
        if ($dbman->field_exists($table, $field)) {
1154
            $dbman->drop_field($table, $field);
1155
        }
1156
 
1157
        // Define field blocking to be dropped from task_scheduled.
1158
        $table = new xmldb_table('task_scheduled');
1159
        $field = new xmldb_field('blocking');
1160
 
1161
        // Conditionally launch drop field blocking.
1162
        if ($dbman->field_exists($table, $field)) {
1163
            $dbman->drop_field($table, $field);
1164
        }
1165
 
1166
        // Main savepoint reached.
1167
        upgrade_main_savepoint(true, 2024041200.00);
1168
    }
1169
 
1170
    // Automatically generated Moodle v4.4.0 release upgrade line.
1171
    // Put any upgrade step following this.
1172
 
11 efrain 1173
    if ($oldversion < 2024042201.09) {
1174
 
1175
        // Fix missing default admin presets "sensible settings" (those that should be treated as sensitive).
1176
        $newsensiblesettings = [
1177
            'bigbluebuttonbn_shared_secret@@none',
1178
            'apikey@@tiny_premium',
1179
            'matrixaccesstoken@@communication_matrix',
1180
            'api_secret@@factor_sms',
1181
        ];
1182
 
1183
        $sensiblesettings = get_config('adminpresets', 'sensiblesettings');
1184
        foreach ($newsensiblesettings as $newsensiblesetting) {
1185
            if (strpos($sensiblesettings, $newsensiblesetting) === false) {
1186
                $sensiblesettings .= ", {$newsensiblesetting}";
1187
            }
1188
        }
1189
 
1190
        set_config('sensiblesettings', $sensiblesettings, 'adminpresets');
1191
 
1192
        // Main savepoint reached.
1193
        upgrade_main_savepoint(true, 2024042201.09);
1194
    }
1195
 
1 efrain 1196
    return true;
1197
}