Differences Between: [Versions 310 and 403] [Versions 311 and 403] [Versions 39 and 403] [Versions 400 and 403] [Versions 401 and 403] [Versions 402 and 403]
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 defined('MOODLE_INTERNAL') || die(); 44 45 /** 46 * Main upgrade tasks to be executed on Moodle version bump 47 * 48 * This function is automatically executed after one bump in the Moodle core 49 * version is detected. It's in charge of performing the required tasks 50 * to raise core from the previous version to the next one. 51 * 52 * It's a collection of ordered blocks of code, named "upgrade steps", 53 * each one performing one isolated (from the rest of steps) task. Usually 54 * tasks involve creating new DB objects or performing manipulation of the 55 * information for cleanup/fixup purposes. 56 * 57 * Each upgrade step has a fixed structure, that can be summarised as follows: 58 * 59 * if ($oldversion < XXXXXXXXXX.XX) { 60 * // Explanation of the update step, linking to issue in the Tracker if necessary 61 * upgrade_set_timeout(XX); // Optional for big tasks 62 * // Code to execute goes here, usually the XMLDB Editor will 63 * // help you here. See {@link https://moodledev.io/general/development/tools/xmldb}. 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 https://moodledev.io/general/development/policies/codingstyle/frankenstyle}, for example: 70 * - {@link xmldb_page_upgrade($oldversion)}. (modules don't require the plugintype ("mod_") to be used. 71 * - {@link xmldb_auth_manual_upgrade($oldversion)}. 72 * - {@link xmldb_workshopform_accumulative_upgrade($oldversion)}. 73 * - .... 74 * 75 * In order to keep the contents of this file reduced, it's allowed to create some helper 76 * functions to be used here in the {@link upgradelib.php} file at the same directory. Note 77 * that such a file must be manually included from upgrade.php, and there are some restrictions 78 * about what can be used within it. 79 * 80 * For more information, take a look to the documentation available: 81 * - Data definition API: {@link https://moodledev.io/docs/apis/core/dml/ddl} 82 * - Upgrade API: {@link https://moodledev.io/docs/guides/upgrade} 83 * 84 * @param int $oldversion 85 * @return bool always true 86 */ 87 function xmldb_main_upgrade($oldversion) { 88 global $CFG, $DB; 89 90 require_once($CFG->libdir.'/db/upgradelib.php'); // Core Upgrade-related functions. 91 92 $dbman = $DB->get_manager(); // Loads ddl manager and xmldb classes. 93 94 // Always keep this upgrade step with version being the minimum 95 // allowed version to upgrade from (v3.11.8 right now). 96 if ($oldversion < 2021051708) { 97 // Just in case somebody hacks upgrade scripts or env, we really can not continue. 98 echo("You need to upgrade to 3.11.8 or higher first!\n"); 99 exit(1); 100 // Note this savepoint is 100% unreachable, but needed to pass the upgrade checks. 101 upgrade_main_savepoint(true, 2021051708); 102 } 103 104 if ($oldversion < 2021052500.01) { 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 109 WHERE f.component = :component 110 AND f.filearea = :filearea 111 AND c.id IS NULL"; 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 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. 134 upgrade_main_savepoint(true, 2021052500.02); 135 } 136 137 if ($oldversion < 2021052500.04) { 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 177 if ($oldversion < 2021052500.05) { 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. 220 upgrade_main_savepoint(true, 2021052500.05); 221 } 222 223 if ($oldversion < 2021052500.06) { 224 // Define table to store virus infected details. 225 $table = new xmldb_table('infected_files'); 226 227 // Adding fields to table infected_files. 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); 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); 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 235 // Adding keys to table infected_files. 236 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 237 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); 238 239 // Conditionally launch create table for infected_files. 240 if (!$dbman->table_exists($table)) { 241 $dbman->create_table($table); 242 } 243 upgrade_main_savepoint(true, 2021052500.06); 244 } 245 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 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 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 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 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'); 336 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 345 if ($oldversion < 2021052500.26) { 346 // Delete orphaned course_modules_completion rows; these were not deleted properly 347 // by remove_course_contents function. 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 )"); 354 upgrade_main_savepoint(true, 2021052500.26); 355 } 356 357 if ($oldversion < 2021052500.27) { 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 376 upgrade_main_savepoint(true, 2021052500.27); 377 } 378 379 if ($oldversion < 2021052500.29) { 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. 412 upgrade_main_savepoint(true, 2021052500.29); 413 } 414 415 if ($oldversion < 2021052500.30) { 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. 423 upgrade_main_savepoint(true, 2021052500.30); 424 } 425 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 439 if ($oldversion < 2021052500.33) { 440 $table = new xmldb_table('badge_backpack'); 441 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']); 448 $dbman->add_key($table, $uniquekey); 449 } 450 451 // Drop the password field as this is moved to badge_backpack. 452 $table = new xmldb_table('badge_external_backpack'); 453 $field = new xmldb_field('password', XMLDB_TYPE_CHAR, '50'); 454 if ($dbman->field_exists($table, $field)) { 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 473 $dbman->drop_field($table, $field); 474 } 475 476 // Main savepoint reached. 477 upgrade_main_savepoint(true, 2021052500.33); 478 } 479 480 if ($oldversion < 2021052500.36) { 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'); 490 $table->add_field('archived', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 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 523 // Define table payments to be created. 524 $table = new xmldb_table('payments'); 525 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); 530 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 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'); 538 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']); 543 544 // Adding indexes to table payments. 545 $table->add_index('gateway', XMLDB_INDEX_NOTUNIQUE, ['gateway']); 546 $table->add_index('component-paymentarea-itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'paymentarea', 'itemid']); 547 548 // Conditionally launch create table for payments. 549 if (!$dbman->table_exists($table)) { 550 $dbman->create_table($table); 551 } 552 553 // Main savepoint reached. 554 upgrade_main_savepoint(true, 2021052500.36); 555 } 556 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 575 if ($oldversion < 2021052500.55) { 576 $DB->delete_records_select('event', "eventtype = 'category' AND categoryid = 0 AND userid <> 0"); 577 578 upgrade_main_savepoint(true, 2021052500.55); 579 } 580 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 595 if ($oldversion < 2021052500.60) { 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. 643 upgrade_main_savepoint(true, 2021052500.60); 644 } 645 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 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 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 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 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 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 748 if ($oldversion < 2021052500.83) { 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. 760 upgrade_main_savepoint(true, 2021052500.83); 761 } 762 763 if ($oldversion < 2021052500.84) { 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. 783 upgrade_main_savepoint(true, 2021052500.84); 784 } 785 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 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 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 838 if ($oldversion < 2021060200.00) { 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. 850 upgrade_main_savepoint(true, 2021060200.00); 851 } 852 853 if ($oldversion < 2021060900.00) { 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. 860 upgrade_main_savepoint(true, 2021060900.00); 861 } 862 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 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 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 948 if ($oldversion < 2021091100.02) { 949 // Set the description field to HTML format for the Default course category. 950 $category = $DB->get_record('course_categories', ['id' => 1]); 951 952 if (!empty($category) && $category->descriptionformat == FORMAT_MOODLE) { 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. 963 upgrade_main_savepoint(true, 2021091100.02); 964 } 965 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 974 if ($oldversion < 2021091700.02) { 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 995 upgrade_main_savepoint(true, 2021091700.02); 996 } 997 998 if ($oldversion < 2021091700.03) { 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 1018 upgrade_main_savepoint(true, 2021091700.03); 1019 } 1020 1021 if ($oldversion < 2021091700.04) { 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 1027 upgrade_main_savepoint(true, 2021091700.04); 1028 } 1029 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 1041 if ($oldversion < 2021092400.03) { 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 1047 upgrade_main_savepoint(true, 2021092400.03); 1048 } 1049 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 1060 if ($oldversion < 2021100300.02) { 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. 1067 upgrade_main_savepoint(true, 2021100300.02); 1068 } 1069 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 1080 if ($oldversion < 2021100600.02) { 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 1092 upgrade_main_savepoint(true, 2021100600.02); 1093 } 1094 1095 if ($oldversion < 2021100600.03) { 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 1106 upgrade_main_savepoint(true, 2021100600.03); 1107 } 1108 1109 if ($oldversion < 2021100600.04) { 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. 1121 upgrade_main_savepoint(true, 2021100600.04); 1122 } 1123 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 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 1228 if ($oldversion < 2021102900.02) { 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 1264 // The boxnet repository plugin stores some config in 'boxnet' incorrectly. 1265 unset_all_config_for_plugin('boxnet'); 1266 1267 // Remove orphaned files. 1268 upgrade_delete_orphaned_file_records(); 1269 } 1270 1271 upgrade_main_savepoint(true, 2021102900.02); 1272 } 1273 1274 if ($oldversion < 2021110100.00) { 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. 1301 upgrade_main_savepoint(true, 2021110100.00); 1302 } 1303 1304 if ($oldversion < 2021110800.02) { 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. 1315 upgrade_main_savepoint(true, 2021110800.02); 1316 } 1317 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 1333 if ($oldversion < 2021111700.00) { 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 1341 upgrade_main_savepoint(true, 2021111700.00); 1342 } 1343 1344 if ($oldversion < 2021111700.01) { 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. 1356 upgrade_main_savepoint(true, 2021111700.01); 1357 } 1358 1359 if ($oldversion < 2021120100.01) { 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. 1374 upgrade_main_savepoint(true, 2021120100.01); 1375 } 1376 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 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 1401 if ($oldversion < 2021122100.00) { 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 1407 calendar,core_calendar|/calendar/view.php?view=month|i/calendar 1408 messages,message|/message/index.php|t/message 1409 preferences,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 1416 grades,grades|/grade/report/mygrades.php 1417 calendar,core_calendar|/calendar/view.php?view=month 1418 privatefiles,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. 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); 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. 1454 upgrade_main_savepoint(true, 2021122100.00); 1455 } 1456 1457 1458 if ($oldversion < 2021122100.01) { 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. 1470 upgrade_main_savepoint(true, 2021122100.01); 1471 } 1472 1473 if ($oldversion < 2021122100.02) { 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); 1487 $table->add_field('messageformat', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 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. 1512 upgrade_main_savepoint(true, 2021122100.02); 1513 } 1514 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. 1701 require_once($CFG->dirroot . '/admin/presets/classes/helper.php'); 1702 \core_adminpresets\helper::create_default_presets(); 1703 } 1704 1705 // Main savepoint reached. 1706 upgrade_main_savepoint(true, 2021123000.01); 1707 } 1708 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 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 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. 1734 $params = ['name' => get_string('fullpreset', 'core_adminpresets')]; 1735 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 1736 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; 1741 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 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 1748 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0"; 1749 $params = ['name' => 'usecomments', 'value' => '1']; 1750 $fullpreset = $DB->get_record_sql($sql, $params); 1751 } 1752 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 1776 if ($oldversion < 2022012100.02) { 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'); 1860 } else { 1861 set_config($provider.'_provider_'.$prefname.'_locked', 0, 'message'); 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 2017 upgrade_main_savepoint(true, 2022012100.02); 2018 } 2019 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); 2055 $table->add_field('questionbankentryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0); 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); 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); 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); 2100 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 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']); 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) { 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'); 2123 $field = new xmldb_field('questionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL); 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 2143 // Main savepoint reached. 2144 upgrade_main_savepoint(true, 2022020200.02); 2145 } 2146 2147 if ($oldversion < 2022020200.03) { 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'); 2172 $field = new xmldb_field('questionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL); 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']); 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 } 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) { 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. 2343 upgrade_main_savepoint(true, 2022020200.07); 2344 } 2345 2346 if ($oldversion < 2022021100.01) { 2347 $sql = "SELECT preset.* 2348 FROM {adminpresets} preset 2349 INNER JOIN {adminpresets_it} it ON preset.id = it.adminpresetid 2350 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0"; 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); 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 2367 $params = ['name' => get_string('fullpreset', 'core_adminpresets')]; 2368 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 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; 2373 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 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 } 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); 2496 2497 } 2498 2499 if ($oldversion < 2022021100.02) { 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. 2516 upgrade_main_savepoint(true, 2022021100.02); 2517 } 2518 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 2540 if ($oldversion < 2022030100.00) { 2541 $sql = "SELECT preset.* 2542 FROM {adminpresets} preset 2543 INNER JOIN {adminpresets_it} it ON preset.id = it.adminpresetid 2544 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0"; 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'); 2570 $params = ['name' => $name]; 2571 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 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; 2576 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 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); 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); 2607 } 2608 2609 // Main savepoint reached. 2610 upgrade_main_savepoint(true, 2022030100.00); 2611 } 2612 2613 if ($oldversion < 2022031100.01) { 2614 $reportsusermenuitem = 'reports,core_reportbuilder|/reportbuilder/index.php'; 2615 upgrade_add_item_to_usermenu($reportsusermenuitem); 2616 // Main savepoint reached. 2617 upgrade_main_savepoint(true, 2022031100.01); 2618 } 2619 2620 if ($oldversion < 2022032200.01) { 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. 2633 upgrade_main_savepoint(true, 2022032200.01); 2634 } 2635 2636 if ($oldversion < 2022032200.02) { 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. 2649 upgrade_main_savepoint(true, 2022032200.02); 2650 } 2651 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 2672 // Automatically generated Moodle v4.0.0 release upgrade line. 2673 // Put any upgrade step following this. 2674 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 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 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 2714 if ($oldversion < 2022052700.01) { 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. 2726 upgrade_main_savepoint(true, 2022052700.01); 2727 } 2728 2729 if ($oldversion < 2022052700.02) { 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. 2741 upgrade_main_savepoint(true, 2022052700.02); 2742 } 2743 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 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 2781 if ($oldversion < 2022061500.00) { 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. 2786 upgrade_main_savepoint(true, 2022061500.00); 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); 2796 } 2797 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 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 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 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 2847 if ($oldversion < 2022101400.03) { 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'); 2855 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'userid'); 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. 2869 upgrade_main_savepoint(true, 2022101400.03); 2870 } 2871 2872 if ($oldversion < 2022101400.04) { 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. 2885 upgrade_main_savepoint(true, 2022101400.04); 2886 } 2887 2888 if ($oldversion < 2022101400.05) { 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. 2899 upgrade_main_savepoint(true, 2022101400.05); 2900 } 2901 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 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 2941 // Automatically generated Moodle v4.1.0 release upgrade line. 2942 // Put any upgrade step following this. 2943 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 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 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 2976 if ($oldversion < 2023020800.00) { 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. 2984 upgrade_main_savepoint(true, 2023020800.00); 2985 } 2986 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 3001 if ($oldversion < 2023022000.00) { 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. 3019 upgrade_main_savepoint(true, 2023022000.00); 3020 } 3021 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 3091 if ($oldversion < 2023030300.02) { 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. 3099 upgrade_main_savepoint(true, 2023030300.02); 3100 } 3101 3102 if ($oldversion < 2023030300.03) { 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 } 3118 upgrade_main_savepoint(true, 2023030300.03); 3119 } 3120 3121 if ($oldversion < 2023031000.02) { 3122 // If editor_tinymce is no longer present, remove it's sub-plugins too. 3123 if (!file_exists($CFG->dirroot . '/lib/editor/tinymce/version.php')) { 3124 $DB->delete_records_select( 3125 'config_plugins', 3126 $DB->sql_like('plugin', ':plugin'), 3127 ['plugin' => $DB->sql_like_escape('tinymce_') . '%'] 3128 ); 3129 } 3130 3131 // Main savepoint reached. 3132 upgrade_main_savepoint(true, 2023031000.02); 3133 } 3134 3135 if ($oldversion < 2023031400.01) { 3136 // Define field id to be added to groups. 3137 $table = new xmldb_table('groups'); 3138 $field = new xmldb_field('visibility', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'picture'); 3139 3140 // Conditionally launch add field visibility. 3141 if (!$dbman->field_exists($table, $field)) { 3142 $dbman->add_field($table, $field); 3143 } 3144 3145 // Define field participation to be added to groups. 3146 $field = new xmldb_field('participation', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'visibility'); 3147 3148 // Conditionally launch add field participation. 3149 if (!$dbman->field_exists($table, $field)) { 3150 $dbman->add_field($table, $field); 3151 } 3152 3153 // Main savepoint reached. 3154 upgrade_main_savepoint(true, 2023031400.01); 3155 } 3156 3157 if ($oldversion < 2023031400.02) { 3158 3159 // Define table xapi_states to be created. 3160 $table = new xmldb_table('xapi_states'); 3161 3162 // Adding fields to table xapi_states. 3163 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3164 $table->add_field('component', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 3165 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 3166 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3167 $table->add_field('stateid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 3168 $table->add_field('statedata', XMLDB_TYPE_TEXT, null, null, null, null, null); 3169 $table->add_field('registration', XMLDB_TYPE_CHAR, '255', null, null, null, null); 3170 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3171 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 3172 3173 // Adding keys to table xapi_states. 3174 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3175 3176 // Adding indexes to table xapi_states. 3177 $table->add_index('component-itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'itemid']); 3178 $table->add_index('userid', XMLDB_INDEX_NOTUNIQUE, ['userid']); 3179 $table->add_index('timemodified', XMLDB_INDEX_NOTUNIQUE, ['timemodified']); 3180 3181 // Conditionally launch create table for xapi_states. 3182 if (!$dbman->table_exists($table)) { 3183 $dbman->create_table($table); 3184 } 3185 3186 if (!isset($CFG->xapicleanupperiod)) { 3187 set_config('xapicleanupperiod', WEEKSECS * 8); 3188 } 3189 3190 // Main savepoint reached. 3191 upgrade_main_savepoint(true, 2023031400.02); 3192 } 3193 3194 if ($oldversion < 2023040600.01) { 3195 // If logstore_legacy is no longer present, remove it. 3196 if (!file_exists($CFG->dirroot . '/admin/tool/log/store/legacy/version.php')) { 3197 uninstall_plugin('logstore', 'legacy'); 3198 } 3199 3200 // Main savepoint reached. 3201 upgrade_main_savepoint(true, 2023040600.01); 3202 } 3203 3204 if ($oldversion < 2023041100.00) { 3205 // Add public key field to user_devices table. 3206 $table = new xmldb_table('user_devices'); 3207 $field = new xmldb_field('publickey', XMLDB_TYPE_TEXT, null, null, null, null, null, 'uuid'); 3208 3209 if (!$dbman->field_exists($table, $field)) { 3210 $dbman->add_field($table, $field); 3211 } 3212 3213 // Main savepoint reached. 3214 upgrade_main_savepoint(true, 2023041100.00); 3215 } 3216 3217 if ($oldversion < 2023042000.00) { 3218 // If mod_assignment is no longer present, remove it. 3219 if (!file_exists($CFG->dirroot . '/mod/assignment/version.php')) { 3220 // Delete all mod_assignment grade_grades orphaned data. 3221 $DB->delete_records_select( 3222 'grade_grades', "itemid IN (SELECT id FROM {grade_items} WHERE itemtype = 'mod' AND itemmodule = 'assignment')" 3223 ); 3224 3225 // Delete all mod_assignment grade_grades_history orphaned data. 3226 $DB->delete_records('grade_grades_history', ['source' => 'mod/assignment']); 3227 3228 // Delete all mod_assignment grade_items orphaned data. 3229 $DB->delete_records('grade_items', ['itemtype' => 'mod', 'itemmodule' => 'assignment']); 3230 3231 // Delete all mod_assignment grade_items_history orphaned data. 3232 $DB->delete_records('grade_items_history', ['itemtype' => 'mod', 'itemmodule' => 'assignment']); 3233 3234 // Delete core mod_assignment subplugins. 3235 uninstall_plugin('assignment', 'offline'); 3236 uninstall_plugin('assignment', 'online'); 3237 uninstall_plugin('assignment', 'upload'); 3238 uninstall_plugin('assignment', 'uploadsingle'); 3239 3240 // Delete other mod_assignment subplugins. 3241 $pluginnamelike = $DB->sql_like('plugin', ':pluginname'); 3242 $subplugins = $DB->get_fieldset_select('config_plugins', 'plugin', "$pluginnamelike AND name = :name", [ 3243 'pluginname' => $DB->sql_like_escape('assignment_') . '%', 3244 'name' => 'version', 3245 ]); 3246 foreach ($subplugins as $subplugin) { 3247 [$plugin, $subpluginname] = explode('_', $subplugin, 2); 3248 uninstall_plugin($plugin, $subpluginname); 3249 } 3250 3251 // Delete mod_assignment. 3252 uninstall_plugin('mod', 'assignment'); 3253 } 3254 3255 // Main savepoint reached. 3256 upgrade_main_savepoint(true, 2023042000.00); 3257 } 3258 3259 // Automatically generated Moodle v4.2.0 release upgrade line. 3260 // Put any upgrade step following this. 3261 3262 if ($oldversion < 2023051500.00) { 3263 // Define communication table. 3264 $table = new xmldb_table('communication'); 3265 3266 // Adding fields to table communication. 3267 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE); 3268 $table->add_field('instanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id'); 3269 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'instanceid'); 3270 $table->add_field('instancetype', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'component'); 3271 $table->add_field('provider', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null, 'instancerype'); 3272 $table->add_field('roomname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'provider'); 3273 $table->add_field('avatarfilename', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'roomname'); 3274 $table->add_field('active', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 1, 'avatarfilename'); 3275 3276 // Add key. 3277 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3278 3279 // Conditionally launch create table for communication. 3280 if (!$dbman->table_exists($table)) { 3281 $dbman->create_table($table); 3282 } 3283 3284 // Define communication user table. 3285 $table = new xmldb_table('communication_user'); 3286 3287 // Adding fields to table communication. 3288 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE); 3289 $table->add_field('commid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'id'); 3290 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null, 'commid'); 3291 $table->add_field('synced', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'userid'); 3292 $table->add_field('deleted', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'synced'); 3293 3294 // Add keys. 3295 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3296 $table->add_key('commid', XMLDB_KEY_FOREIGN, ['commid'], 'communication', ['id']); 3297 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); 3298 3299 // Conditionally launch create table for communication. 3300 if (!$dbman->table_exists($table)) { 3301 $dbman->create_table($table); 3302 } 3303 3304 // Main savepoint reached. 3305 upgrade_main_savepoint(true, 2023051500.00); 3306 } 3307 3308 if ($oldversion < 2023062200.00) { 3309 // Remove device specific fields for themes from config table. 3310 unset_config('thememobile'); 3311 unset_config('themelegacy'); 3312 unset_config('themetablet'); 3313 3314 upgrade_main_savepoint(true, 2023062200.00); 3315 } 3316 3317 if ($oldversion < 2023062700.01) { 3318 // Define field name to be added to external_tokens. 3319 $table = new xmldb_table('external_tokens'); 3320 $field = new xmldb_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'lastaccess'); 3321 // Conditionally launch add field name. 3322 if (!$dbman->field_exists($table, $field)) { 3323 $dbman->add_field($table, $field); 3324 } 3325 // Update the old external tokens. 3326 $sql = 'UPDATE {external_tokens} 3327 SET name = ' . $DB->sql_concat( 3328 // We only need the prefix, so leave the third param with an empty string. 3329 "'" . get_string('tokennameprefix', 'webservice', '') . "'", 3330 "id"); 3331 $DB->execute($sql); 3332 // Main savepoint reached. 3333 upgrade_main_savepoint(true, 2023062700.01); 3334 } 3335 3336 if ($oldversion < 2023062900.01) { 3337 3338 // Define field avatarsynced to be added to communication. 3339 $table = new xmldb_table('communication'); 3340 $field = new xmldb_field('avatarsynced', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, 0, 'active'); 3341 3342 // Conditionally launch add field avatarsynced. 3343 if (!$dbman->field_exists($table, $field)) { 3344 $dbman->add_field($table, $field); 3345 } 3346 3347 // Main savepoint reached. 3348 upgrade_main_savepoint(true, 2023062900.01); 3349 } 3350 3351 if ($oldversion < 2023080100.00) { 3352 // Upgrade yaml mime type for existing yaml and yml files. 3353 $filetypes = [ 3354 '%.yaml' => 'application/yaml', 3355 '%.yml' => 'application/yaml,' 3356 ]; 3357 3358 $select = $DB->sql_like('filename', '?', false); 3359 foreach ($filetypes as $extension => $mimetype) { 3360 $DB->set_field_select( 3361 'files', 3362 'mimetype', 3363 $mimetype, 3364 $select, 3365 [$extension] 3366 ); 3367 } 3368 3369 // Main savepoint reached. 3370 upgrade_main_savepoint(true, 2023080100.00); 3371 } 3372 3373 if ($oldversion < 2023081500.00) { 3374 upgrade_core_licenses(); 3375 upgrade_main_savepoint(true, 2023081500.00); 3376 } 3377 3378 if ($oldversion < 2023081800.01) { 3379 // Remove enabledevicedetection and devicedetectregex from config table. 3380 unset_config('enabledevicedetection'); 3381 unset_config('devicedetectregex'); 3382 // Main savepoint reached. 3383 upgrade_main_savepoint(true, 2023081800.01); 3384 } 3385 3386 if ($oldversion < 2023082200.01) { 3387 // Some MIME icons have been removed and replaced with existing icons. They need to be upgraded for custom MIME types. 3388 $replacedicons = [ 3389 'avi' => 'video', 3390 'base' => 'database', 3391 'bmp' => 'image', 3392 'html' => 'markup', 3393 'jpeg' => 'image', 3394 'mov' => 'video', 3395 'mp3' => 'audio', 3396 'mpeg' => 'video', 3397 'png' => 'image', 3398 'quicktime' => 'video', 3399 'tiff' => 'image', 3400 'wav' => 'audio', 3401 'wmv' => 'video', 3402 ]; 3403 3404 $custom = []; 3405 if (!empty($CFG->customfiletypes)) { 3406 if (array_key_exists('customfiletypes', $CFG->config_php_settings)) { 3407 // It's set in config.php, so the MIME icons can't be upgraded automatically. 3408 echo("\nYou need to manually check customfiletypes in config.php because some MIME icons have been removed!\n"); 3409 } else { 3410 // It's a JSON string in the config table. 3411 $custom = json_decode($CFG->customfiletypes); 3412 } 3413 } 3414 3415 $changed = false; 3416 foreach ($custom as $customentry) { 3417 if (!empty($customentry->icon) && array_key_exists($customentry->icon, $replacedicons)) { 3418 $customentry->icon = $replacedicons[$customentry->icon]; 3419 $changed = true; 3420 } 3421 } 3422 3423 if ($changed) { 3424 // Save the new customfiletypes. 3425 set_config('customfiletypes', json_encode($custom)); 3426 } 3427 3428 // Main savepoint reached. 3429 upgrade_main_savepoint(true, 2023082200.01); 3430 } 3431 3432 if ($oldversion < 2023082200.02) { 3433 // Some MIME icons have been removed. They need to be replaced to 'unknown' for custom MIME types. 3434 $removedicons = array_flip([ 3435 'clip-353', 3436 'edit', 3437 'env', 3438 'explore', 3439 'folder-open', 3440 'help', 3441 'move', 3442 'parent', 3443 ]); 3444 3445 $custom = []; 3446 if (!empty($CFG->customfiletypes)) { 3447 if (array_key_exists('customfiletypes', $CFG->config_php_settings)) { 3448 // It's set in config.php, so the MIME icons can't be upgraded automatically. 3449 echo("\nYou need to manually check customfiletypes in config.php because some MIME icons have been removed!\n"); 3450 } else { 3451 // It's a JSON string in the config table. 3452 $custom = json_decode($CFG->customfiletypes); 3453 } 3454 } 3455 3456 $changed = false; 3457 foreach ($custom as $customentry) { 3458 if (!empty($customentry->icon) && array_key_exists($customentry->icon, $removedicons)) { 3459 // The icon has been removed, so set it to unknown. 3460 $customentry->icon = 'unknown'; 3461 $changed = true; 3462 } 3463 } 3464 3465 if ($changed) { 3466 // Save the new customfiletypes. 3467 set_config('customfiletypes', json_encode($custom)); 3468 } 3469 3470 // Main savepoint reached. 3471 upgrade_main_savepoint(true, 2023082200.02); 3472 } 3473 3474 if ($oldversion < 2023082200.04) { 3475 3476 // Remove any non-unique filters/conditions. 3477 $duplicates = $DB->get_records_sql(" 3478 SELECT MIN(id) AS id, reportid, uniqueidentifier, iscondition 3479 FROM {reportbuilder_filter} 3480 GROUP BY reportid, uniqueidentifier, iscondition 3481 HAVING COUNT(*) > 1"); 3482 3483 foreach ($duplicates as $duplicate) { 3484 $DB->delete_records_select( 3485 'reportbuilder_filter', 3486 'id <> :id AND reportid = :reportid AND uniqueidentifier = :uniqueidentifier AND iscondition = :iscondition', 3487 (array) $duplicate 3488 ); 3489 } 3490 3491 // Define index report-filter (unique) to be added to reportbuilder_filter. 3492 $table = new xmldb_table('reportbuilder_filter'); 3493 $index = new xmldb_index('report-filter', XMLDB_INDEX_UNIQUE, ['reportid', 'uniqueidentifier', 'iscondition']); 3494 3495 // Conditionally launch add index report-filter. 3496 if (!$dbman->index_exists($table, $index)) { 3497 $dbman->add_index($table, $index); 3498 } 3499 3500 // Main savepoint reached. 3501 upgrade_main_savepoint(true, 2023082200.04); 3502 } 3503 3504 if ($oldversion < 2023082600.02) { 3505 // Get all the ids of users who still have md5 hashed passwords. 3506 if ($DB->sql_regex_supported()) { 3507 // If the database supports regex, we can add an exact check for md5. 3508 $condition = 'password ' . $DB->sql_regex() . ' :pattern'; 3509 $params = ['pattern' => "^[a-fA-F0-9]{32}$"]; 3510 } else { 3511 // Otherwise, we need to use a NOT LIKE condition and rule out bcrypt. 3512 $condition = $DB->sql_like('password', ':pattern', true, false, true); 3513 $params = ['pattern' => '$2y$%']; 3514 } 3515 3516 // Regardless of database regex support we check the hash length which should be enough. 3517 // But extra regex or like matching makes sure. 3518 $sql = "SELECT id FROM {user} WHERE " . $DB->sql_length('password') . " = 32 AND $condition"; 3519 $userids = $DB->get_fieldset_sql($sql, $params); 3520 3521 // Update the password for each user with a new SHA-512 hash. 3522 // Users won't know this password, but they can reset it. This is a security measure, 3523 // in case the database is compromised or the hash has been leaked elsewhere. 3524 foreach ($userids as $userid) { 3525 $password = base64_encode(random_bytes(24)); // Generate a new password for the user. 3526 3527 $user = new \stdClass(); 3528 $user->id = $userid; 3529 $user->password = hash_internal_user_password($password); 3530 $DB->update_record('user', $user, true); 3531 } 3532 3533 // Main savepoint reached. 3534 upgrade_main_savepoint(true, 2023082600.02); 3535 } 3536 3537 if ($oldversion < 2023082600.03) { 3538 // The previous default configuration had a typo, check for its presence and correct if necessary. 3539 $sensiblesettings = get_config('adminpresets', 'sensiblesettings'); 3540 if (strpos($sensiblesettings, 'smtppass@none') !== false) { 3541 $newsensiblesettings = str_replace('smtppass@none', 'smtppass@@none', $sensiblesettings); 3542 set_config('sensiblesettings', $newsensiblesettings, 'adminpresets'); 3543 } 3544 3545 // Main savepoint reached. 3546 upgrade_main_savepoint(true, 2023082600.03); 3547 } 3548 3549 if ($oldversion < 2023082600.05) { 3550 unset_config('completiondefault'); 3551 3552 // Main savepoint reached. 3553 upgrade_main_savepoint(true, 2023082600.05); 3554 } 3555 3556 if ($oldversion < 2023090100.00) { 3557 // Upgrade MIME type for existing PSD files. 3558 $DB->set_field_select( 3559 'files', 3560 'mimetype', 3561 'image/vnd.adobe.photoshop', 3562 $DB->sql_like('filename', '?', false), 3563 ['%.psd'] 3564 ); 3565 3566 // Main savepoint reached. 3567 upgrade_main_savepoint(true, 2023090100.00); 3568 } 3569 3570 if ($oldversion < 2023090200.01) { 3571 3572 // Define table moodlenet_share_progress to be created. 3573 $table = new xmldb_table('moodlenet_share_progress'); 3574 3575 // Adding fields to table moodlenet_share_progress. 3576 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3577 $table->add_field('type', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, null); 3578 $table->add_field('courseid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3579 $table->add_field('cmid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 3580 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3581 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3582 $table->add_field('resourceurl', XMLDB_TYPE_CHAR, '255', null, null, null, null); 3583 $table->add_field('status', XMLDB_TYPE_INTEGER, '2', null, null, null, null); 3584 3585 // Adding keys to table moodlenet_share_progress. 3586 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3587 3588 // Conditionally launch create table for moodlenet_share_progress. 3589 if (!$dbman->table_exists($table)) { 3590 $dbman->create_table($table); 3591 } 3592 3593 // Main savepoint reached. 3594 upgrade_main_savepoint(true, 2023090200.01); 3595 } 3596 3597 if ($oldversion < 2023091300.03) { 3598 // Delete all the searchanywhere prefs in user_preferences table. 3599 $DB->delete_records('user_preferences', ['name' => 'userselector_searchanywhere']); 3600 // Main savepoint reached. 3601 upgrade_main_savepoint(true, 2023091300.03); 3602 } 3603 3604 if ($oldversion < 2023100400.01) { 3605 // Delete datakey with datavalue -1. 3606 $DB->delete_records('messageinbound_datakeys', ['datavalue' => '-1']); 3607 // Main savepoint reached. 3608 upgrade_main_savepoint(true, 2023100400.01); 3609 } 3610 3611 if ($oldversion < 2023100400.03) { 3612 // Define field id to be added to communication. 3613 $table = new xmldb_table('communication'); 3614 3615 // Add the field and allow it to be nullable. 3616 // We need to backfill data before setting it to NOT NULL. 3617 $field = new xmldb_field( 3618 name: 'contextid', 3619 type: XMLDB_TYPE_INTEGER, 3620 precision: '10', 3621 notnull: null, 3622 previous: 'id', 3623 ); 3624 3625 // Conditionally launch add field id. 3626 if (!$dbman->field_exists($table, $field)) { 3627 $dbman->add_field($table, $field); 3628 } 3629 3630 // Fill the existing data. 3631 $sql = <<<EOF 3632 SELECT comm.id, c.id AS contextid 3633 FROM {communication} comm 3634 INNER JOIN {context} c ON c.instanceid = comm.instanceid AND c.contextlevel = :contextcourse 3635 WHERE comm.contextid IS NULL 3636 AND comm.instancetype = :instancetype 3637 EOF; 3638 $rs = $DB->get_recordset_sql( 3639 sql: $sql, 3640 params: [ 3641 'contextcourse' => CONTEXT_COURSE, 3642 'instancetype' => 'coursecommunication', 3643 ], 3644 ); 3645 foreach ($rs as $comm) { 3646 $DB->set_field( 3647 table: 'communication', 3648 newfield: 'contextid', 3649 newvalue: $comm->contextid, 3650 conditions: [ 3651 'id' => $comm->id, 3652 ], 3653 ); 3654 } 3655 $rs->close(); 3656 3657 $systemcontext = \core\context\system::instance(); 3658 $DB->set_field_select( 3659 table: 'communication', 3660 newfield: 'contextid', 3661 newvalue: $systemcontext->id, 3662 select: 'contextid IS NULL', 3663 ); 3664 3665 // Now make it NOTNULL. 3666 $field = new xmldb_field( 3667 name: 'contextid', 3668 type: XMLDB_TYPE_INTEGER, 3669 precision: '10', 3670 notnull: XMLDB_NOTNULL, 3671 ); 3672 $dbman->change_field_notnull($table, $field); 3673 3674 // Add the contextid constraint. 3675 $key = new xmldb_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']); 3676 $dbman->add_key($table, $key); 3677 3678 // Main savepoint reached. 3679 upgrade_main_savepoint(true, 2023100400.03); 3680 } 3681 3682 // Automatically generated Moodle v4.3.0 release upgrade line. 3683 // Put any upgrade step following this. 3684 3685 return true; 3686 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body