Differences Between: [Versions 310 and 400] [Versions 311 and 400] [Versions 39 and 400] [Versions 400 and 401] [Versions 400 and 402] [Versions 400 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 http://docs.moodle.org/dev/XMLDB_editor}. 64 * upgrade_main_savepoint(true, XXXXXXXXXX.XX); 65 * } 66 * 67 * All plugins within Moodle (modules, blocks, reports...) support the existence of 68 * their own upgrade.php file, using the "Frankenstyle" component name as 69 * defined at {@link http://docs.moodle.org/dev/Frankenstyle}, for example: 70 * - {@link xmldb_page_upgrade($oldversion)}. (modules don't require the plugintype ("mod_") to be used. 71 * - {@link xmldb_auth_manual_upgrade($oldversion)}. 72 * - {@link xmldb_workshopform_accumulative_upgrade($oldversion)}. 73 * - .... 74 * 75 * In order to keep the contents of this file reduced, it's allowed to create some helper 76 * functions to be used here in the {@link upgradelib.php} file at the same directory. Note 77 * that such a file must be manually included from upgrade.php, and there are some restrictions 78 * about what can be used within it. 79 * 80 * For more information, take a look to the documentation available: 81 * - Data definition API: {@link http://docs.moodle.org/dev/Data_definition_API} 82 * - Upgrade API: {@link http://docs.moodle.org/dev/Upgrade_API} 83 * 84 * @param int $oldversion 85 * @return bool always true 86 */ 87 function xmldb_main_upgrade($oldversion) { 88 global $CFG, $DB; 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.6.0 right now). 96 if ($oldversion < 2018120300) { 97 // Just in case somebody hacks upgrade scripts or env, we really can not continue. 98 echo("You need to upgrade to 3.6.x or higher first!\n"); 99 exit(1); 100 // Note this savepoint is 100% unreachable, but needed to pass the upgrade checks. 101 upgrade_main_savepoint(true, 2018120300); 102 } 103 104 // Automatically generated Moodle v3.6.0 release upgrade line. 105 // Put any upgrade step following this. 106 107 if ($oldversion < 2018120300.01) { 108 // Update the FB logo URL. 109 $oldurl = 'https://facebookbrand.com/wp-content/themes/fb-branding/prj-fb-branding/assets/images/fb-art.png'; 110 $newurl = 'https://facebookbrand.com/wp-content/uploads/2016/05/flogo_rgb_hex-brc-site-250.png'; 111 112 $updatesql = "UPDATE {oauth2_issuer} 113 SET image = :newimage 114 WHERE " . $DB->sql_compare_text('image', 100). " = :oldimage"; 115 $params = [ 116 'newimage' => $newurl, 117 'oldimage' => $oldurl 118 ]; 119 $DB->execute($updatesql, $params); 120 121 upgrade_main_savepoint(true, 2018120300.01); 122 } 123 124 if ($oldversion < 2018120300.02) { 125 // Set all individual conversations to enabled. 126 $updatesql = "UPDATE {message_conversations} 127 SET enabled = :enabled 128 WHERE type = :type"; 129 $DB->execute($updatesql, ['enabled' => 1, 'type' => 1]); 130 131 upgrade_main_savepoint(true, 2018120300.02); 132 } 133 134 if ($oldversion < 2018120301.02) { 135 upgrade_delete_orphaned_file_records(); 136 upgrade_main_savepoint(true, 2018120301.02); 137 } 138 139 if ($oldversion < 2019011500.00) { 140 // Define table task_log to be created. 141 $table = new xmldb_table('task_log'); 142 143 // Adding fields to table task_log. 144 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 145 $table->add_field('type', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null); 146 $table->add_field('component', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 147 $table->add_field('classname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 148 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 149 $table->add_field('timestart', XMLDB_TYPE_NUMBER, '20, 10', null, XMLDB_NOTNULL, null, null); 150 $table->add_field('timeend', XMLDB_TYPE_NUMBER, '20, 10', null, XMLDB_NOTNULL, null, null); 151 $table->add_field('dbreads', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 152 $table->add_field('dbwrites', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 153 $table->add_field('result', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, null); 154 155 // Adding keys to table task_log. 156 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 157 158 // Adding indexes to table task_log. 159 $table->add_index('classname', XMLDB_INDEX_NOTUNIQUE, ['classname']); 160 $table->add_index('timestart', XMLDB_INDEX_NOTUNIQUE, ['timestart']); 161 162 // Conditionally launch create table for task_log. 163 if (!$dbman->table_exists($table)) { 164 $dbman->create_table($table); 165 } 166 167 // Main savepoint reached. 168 upgrade_main_savepoint(true, 2019011500.00); 169 } 170 171 if ($oldversion < 2019011501.00) { 172 // Define field output to be added to task_log. 173 $table = new xmldb_table('task_log'); 174 $field = new xmldb_field('output', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null, 'result'); 175 176 // Conditionally launch add field output. 177 if (!$dbman->field_exists($table, $field)) { 178 $dbman->add_field($table, $field); 179 } 180 181 // Main savepoint reached. 182 upgrade_main_savepoint(true, 2019011501.00); 183 } 184 185 if ($oldversion < 2019011801.00) { 186 187 // Define table customfield_category to be created. 188 $table = new xmldb_table('customfield_category'); 189 190 // Adding fields to table customfield_category. 191 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 192 $table->add_field('name', XMLDB_TYPE_CHAR, '400', null, XMLDB_NOTNULL, null, null); 193 $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null); 194 $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 195 $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 196 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 197 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 198 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 199 $table->add_field('area', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 200 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 201 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 202 203 // Adding keys to table customfield_category. 204 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 205 $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']); 206 207 // Adding indexes to table customfield_category. 208 $table->add_index('component_area_itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'area', 'itemid', 'sortorder']); 209 210 // Conditionally launch create table for customfield_category. 211 if (!$dbman->table_exists($table)) { 212 $dbman->create_table($table); 213 } 214 215 // Define table customfield_field to be created. 216 $table = new xmldb_table('customfield_field'); 217 218 // Adding fields to table customfield_field. 219 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 220 $table->add_field('shortname', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 221 $table->add_field('name', XMLDB_TYPE_CHAR, '400', null, XMLDB_NOTNULL, null, null); 222 $table->add_field('type', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 223 $table->add_field('description', XMLDB_TYPE_TEXT, null, null, null, null, null); 224 $table->add_field('descriptionformat', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 225 $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 226 $table->add_field('categoryid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 227 $table->add_field('configdata', XMLDB_TYPE_TEXT, null, null, null, null, null); 228 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 229 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 230 231 // Adding keys to table customfield_field. 232 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 233 $table->add_key('categoryid', XMLDB_KEY_FOREIGN, ['categoryid'], 'customfield_category', ['id']); 234 235 // Adding indexes to table customfield_field. 236 $table->add_index('categoryid_sortorder', XMLDB_INDEX_NOTUNIQUE, ['categoryid', 'sortorder']); 237 238 // Conditionally launch create table for customfield_field. 239 if (!$dbman->table_exists($table)) { 240 $dbman->create_table($table); 241 } 242 243 // Define table customfield_data to be created. 244 $table = new xmldb_table('customfield_data'); 245 246 // Adding fields to table customfield_data. 247 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 248 $table->add_field('fieldid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 249 $table->add_field('instanceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 250 $table->add_field('intvalue', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 251 $table->add_field('decvalue', XMLDB_TYPE_NUMBER, '10, 5', null, null, null, null); 252 $table->add_field('shortcharvalue', XMLDB_TYPE_CHAR, '255', null, null, null, null); 253 $table->add_field('charvalue', XMLDB_TYPE_CHAR, '1333', null, null, null, null); 254 $table->add_field('value', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); 255 $table->add_field('valueformat', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 256 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 257 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 258 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 259 260 // Adding keys to table customfield_data. 261 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 262 $table->add_key('fieldid', XMLDB_KEY_FOREIGN, ['fieldid'], 'customfield_field', ['id']); 263 $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']); 264 265 // Adding indexes to table customfield_data. 266 $table->add_index('instanceid-fieldid', XMLDB_INDEX_UNIQUE, ['instanceid', 'fieldid']); 267 $table->add_index('fieldid-intvalue', XMLDB_INDEX_NOTUNIQUE, ['fieldid', 'intvalue']); 268 $table->add_index('fieldid-shortcharvalue', XMLDB_INDEX_NOTUNIQUE, ['fieldid', 'shortcharvalue']); 269 $table->add_index('fieldid-decvalue', XMLDB_INDEX_NOTUNIQUE, ['fieldid', 'decvalue']); 270 271 // Conditionally launch create table for customfield_data. 272 if (!$dbman->table_exists($table)) { 273 $dbman->create_table($table); 274 } 275 276 upgrade_main_savepoint(true, 2019011801.00); 277 } 278 279 if ($oldversion < 2019011801.01) { 280 281 // Delete all files that have been used in sections, which are already deleted. 282 $sql = "SELECT DISTINCT f.itemid as sectionid, f.contextid 283 FROM {files} f 284 LEFT JOIN {course_sections} s ON f.itemid = s.id 285 WHERE f.component = :component AND f.filearea = :filearea AND s.id IS NULL "; 286 287 $params = [ 288 'component' => 'course', 289 'filearea' => 'section' 290 ]; 291 292 $stalefiles = $DB->get_recordset_sql($sql, $params); 293 294 $fs = get_file_storage(); 295 foreach ($stalefiles as $stalefile) { 296 $fs->delete_area_files($stalefile->contextid, 'course', 'section', $stalefile->sectionid); 297 } 298 $stalefiles->close(); 299 300 upgrade_main_savepoint(true, 2019011801.01); 301 } 302 303 if ($oldversion < 2019011801.02) { 304 // Add index 'useridfrom' to the table 'notifications'. 305 $table = new xmldb_table('notifications'); 306 $index = new xmldb_index('useridfrom', XMLDB_INDEX_NOTUNIQUE, ['useridfrom']); 307 308 if (!$dbman->index_exists($table, $index)) { 309 $dbman->add_index($table, $index); 310 } 311 312 upgrade_main_savepoint(true, 2019011801.02); 313 } 314 315 if ($oldversion < 2019011801.03) { 316 // Remove duplicate entries from group memberships. 317 // Find records with multiple userid/groupid combinations and find the highest ID. 318 // Later we will remove all those entries. 319 $sql = " 320 SELECT MIN(id) as minid, userid, groupid 321 FROM {groups_members} 322 GROUP BY userid, groupid 323 HAVING COUNT(id) > 1"; 324 if ($duplicatedrows = $DB->get_recordset_sql($sql)) { 325 foreach ($duplicatedrows as $row) { 326 $DB->delete_records_select('groups_members', 327 'userid = :userid AND groupid = :groupid AND id <> :minid', (array)$row); 328 } 329 } 330 $duplicatedrows->close(); 331 332 // Define key useridgroupid (unique) to be added to group_members. 333 $table = new xmldb_table('groups_members'); 334 $key = new xmldb_key('useridgroupid', XMLDB_KEY_UNIQUE, array('userid', 'groupid')); 335 // Launch add key useridgroupid. 336 $dbman->add_key($table, $key); 337 // Main savepoint reached. 338 upgrade_main_savepoint(true, 2019011801.03); 339 } 340 341 if ($oldversion < 2019021500.01) { 342 $insights = $DB->get_record('message_providers', ['component' => 'moodle', 'name' => 'insights']); 343 if (!empty($insights)) { 344 $insights->capability = null; 345 $DB->update_record('message_providers', $insights); 346 } 347 upgrade_main_savepoint(true, 2019021500.01); 348 } 349 350 if ($oldversion < 2019021500.02) { 351 // Default 'off' for existing sites as this is the behaviour they had earlier. 352 set_config('messagingdefaultpressenter', false); 353 354 // Main savepoint reached. 355 upgrade_main_savepoint(true, 2019021500.02); 356 } 357 358 if ($oldversion < 2019030100.01) { 359 // Create adhoc task to delete renamed My Course search area (ID core_course-mycourse). 360 $record = new \stdClass(); 361 $record->classname = '\core\task\clean_up_deleted_search_area_task'; 362 $record->component = 'core'; 363 364 // Next run time based from nextruntime computation in \core\task\manager::queue_adhoc_task(). 365 $nextruntime = time() - 1; 366 $record->nextruntime = $nextruntime; 367 $record->customdata = json_encode('core_course-mycourse'); 368 369 $DB->insert_record('task_adhoc', $record); 370 371 // Main savepoint reached. 372 upgrade_main_savepoint(true, 2019030100.01); 373 } 374 375 if ($oldversion < 2019030700.01) { 376 377 // Define field evaluationmode to be added to analytics_models_log. 378 $table = new xmldb_table('analytics_models_log'); 379 $field = new xmldb_field('evaluationmode', XMLDB_TYPE_CHAR, '50', null, null, null, 380 null, 'version'); 381 382 // Conditionally launch add field evaluationmode. 383 if (!$dbman->field_exists($table, $field)) { 384 $dbman->add_field($table, $field); 385 386 $updatesql = "UPDATE {analytics_models_log} 387 SET evaluationmode = 'configuration'"; 388 $DB->execute($updatesql, []); 389 390 // Changing nullability of field evaluationmode on table block_instances to not null. 391 $field = new xmldb_field('evaluationmode', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL, 392 null, null, 'version'); 393 394 // Launch change of nullability for field evaluationmode. 395 $dbman->change_field_notnull($table, $field); 396 } 397 398 // Main savepoint reached. 399 upgrade_main_savepoint(true, 2019030700.01); 400 } 401 402 if ($oldversion < 2019030800.00) { 403 // Define table 'message_conversation_actions' to be created. 404 // Note - I would have preferred 'message_conversation_user_actions' but due to Oracle we can't. Boo. 405 $table = new xmldb_table('message_conversation_actions'); 406 407 // Adding fields to table 'message_conversation_actions'. 408 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 409 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 410 $table->add_field('conversationid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 411 $table->add_field('action', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 412 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 413 414 // Adding keys to table 'message_conversation_actions'. 415 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 416 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); 417 $table->add_key('conversationid', XMLDB_KEY_FOREIGN, ['conversationid'], 'message_conversations', ['id']); 418 419 // Conditionally launch create table for 'message_conversation_actions'. 420 if (!$dbman->table_exists($table)) { 421 $dbman->create_table($table); 422 } 423 424 // Main savepoint reached. 425 upgrade_main_savepoint(true, 2019030800.00); 426 } 427 428 if ($oldversion < 2019030800.02) { 429 // Remove any conversations and their members associated with non-existent groups. 430 $sql = "SELECT mc.id 431 FROM {message_conversations} mc 432 LEFT JOIN {groups} g 433 ON mc.itemid = g.id 434 WHERE mc.component = :component 435 AND mc.itemtype = :itemtype 436 AND g.id is NULL"; 437 $conversations = $DB->get_records_sql($sql, ['component' => 'core_group', 'itemtype' => 'groups']); 438 439 if ($conversations) { 440 $conversationids = array_keys($conversations); 441 442 $DB->delete_records_list('message_conversations', 'id', $conversationids); 443 $DB->delete_records_list('message_conversation_members', 'conversationid', $conversationids); 444 $DB->delete_records_list('message_conversation_actions', 'conversationid', $conversationids); 445 446 // Now, go through each conversation and delete any messages and related message actions. 447 foreach ($conversationids as $conversationid) { 448 if ($messages = $DB->get_records('messages', ['conversationid' => $conversationid])) { 449 $messageids = array_keys($messages); 450 451 // Delete the actions. 452 list($insql, $inparams) = $DB->get_in_or_equal($messageids); 453 $DB->delete_records_select('message_user_actions', "messageid $insql", $inparams); 454 455 // Delete the messages. 456 $DB->delete_records('messages', ['conversationid' => $conversationid]); 457 } 458 } 459 } 460 461 // Main savepoint reached. 462 upgrade_main_savepoint(true, 2019030800.02); 463 } 464 465 if ($oldversion < 2019030800.03) { 466 467 // Add missing indicators to course_dropout. 468 $params = [ 469 'target' => '\core\analytics\target\course_dropout', 470 'trained' => 0, 471 'enabled' => 0, 472 ]; 473 $models = $DB->get_records('analytics_models', $params); 474 foreach ($models as $model) { 475 $indicators = json_decode($model->indicators); 476 477 $potentiallymissingindicators = [ 478 '\core_course\analytics\indicator\completion_enabled', 479 '\core_course\analytics\indicator\potential_cognitive_depth', 480 '\core_course\analytics\indicator\potential_social_breadth', 481 '\core\analytics\indicator\any_access_after_end', 482 '\core\analytics\indicator\any_access_before_start', 483 '\core\analytics\indicator\any_write_action_in_course', 484 '\core\analytics\indicator\read_actions' 485 ]; 486 487 $missing = false; 488 foreach ($potentiallymissingindicators as $potentiallymissingindicator) { 489 if (!in_array($potentiallymissingindicator, $indicators)) { 490 // Add the missing indicator to sites upgraded before 2017072000.02. 491 $indicators[] = $potentiallymissingindicator; 492 $missing = true; 493 } 494 } 495 496 if ($missing) { 497 $model->indicators = json_encode($indicators); 498 $model->version = time(); 499 $model->timemodified = time(); 500 $DB->update_record('analytics_models', $model); 501 } 502 } 503 504 // Add missing indicators to no_teaching. 505 $params = [ 506 'target' => '\core\analytics\target\no_teaching', 507 ]; 508 $models = $DB->get_records('analytics_models', $params); 509 foreach ($models as $model) { 510 $indicators = json_decode($model->indicators); 511 if (!in_array('\core_course\analytics\indicator\no_student', $indicators)) { 512 // Add the missing indicator to sites upgraded before 2017072000.02. 513 514 $indicators[] = '\core_course\analytics\indicator\no_student'; 515 516 $model->indicators = json_encode($indicators); 517 $model->version = time(); 518 $model->timemodified = time(); 519 $DB->update_record('analytics_models', $model); 520 } 521 } 522 523 // Main savepoint reached. 524 upgrade_main_savepoint(true, 2019030800.03); 525 } 526 527 if ($oldversion < 2019031500.01) { 528 529 $defaulttimesplittings = get_config('analytics', 'timesplittings'); 530 if ($defaulttimesplittings !== false) { 531 set_config('defaulttimesplittingsevaluation', $defaulttimesplittings, 'analytics'); 532 unset_config('timesplittings', 'analytics'); 533 } 534 535 // Main savepoint reached. 536 upgrade_main_savepoint(true, 2019031500.01); 537 } 538 539 if ($oldversion < 2019032200.02) { 540 // The no_teaching model might have been marked as not-trained by mistake (static models are always trained). 541 $DB->set_field('analytics_models', 'trained', 1, ['target' => '\core\analytics\target\no_teaching']); 542 upgrade_main_savepoint(true, 2019032200.02); 543 } 544 545 if ($oldversion < 2019032900.00) { 546 547 // Define table badge_competencies to be renamed to badge_alignment. 548 $table = new xmldb_table('badge_competencies'); 549 550 // Be careful if this step gets run twice. 551 if ($dbman->table_exists($table)) { 552 $key = new xmldb_key('competenciesbadge', XMLDB_KEY_FOREIGN, ['badgeid'], 'badge', ['id']); 553 554 // Launch drop key competenciesbadge. 555 $dbman->drop_key($table, $key); 556 557 $key = new xmldb_key('alignmentsbadge', XMLDB_KEY_FOREIGN, ['badgeid'], 'badge', ['id']); 558 559 // Launch add key alignmentsbadge. 560 $dbman->add_key($table, $key); 561 562 // Launch rename table for badge_alignment. 563 $dbman->rename_table($table, 'badge_alignment'); 564 } 565 566 upgrade_main_savepoint(true, 2019032900.00); 567 } 568 569 if ($oldversion < 2019032900.01) { 570 $sql = "UPDATE {task_scheduled} 571 SET classname = ? 572 WHERE component = ? 573 AND classname = ?"; 574 $DB->execute($sql, [ 575 '\core\task\question_preview_cleanup_task', 576 'moodle', 577 '\core\task\question_cron_task' 578 ]); 579 580 // Main savepoint reached. 581 upgrade_main_savepoint(true, 2019032900.01); 582 } 583 584 if ($oldversion < 2019040200.01) { 585 // Removing the themes BSB, Clean, More from core. 586 // If these theme wish to be retained empty this array before upgrade. 587 $themes = array('theme_bootstrapbase' => 'bootstrapbase', 588 'theme_clean' => 'clean', 'theme_more' => 'more'); 589 foreach ($themes as $key => $theme) { 590 if (check_dir_exists($CFG->dirroot . '/theme/' . $theme, false)) { 591 // Ignore the themes that have been re-downloaded. 592 unset($themes[$key]); 593 } 594 } 595 // Check we actually have themes to remove. 596 if (count($themes) > 0) { 597 list($insql, $inparams) = $DB->get_in_or_equal($themes, SQL_PARAMS_NAMED); 598 599 // Replace the theme usage. 600 $DB->set_field_select('course', 'theme', 'classic', "theme $insql", $inparams); 601 $DB->set_field_select('course_categories', 'theme', 'classic', "theme $insql", $inparams); 602 $DB->set_field_select('user', 'theme', 'classic', "theme $insql", $inparams); 603 $DB->set_field_select('mnet_host', 'theme', 'classic', "theme $insql", $inparams); 604 $DB->set_field_select('cohort', 'theme', 'classic', "theme $insql", $inparams); 605 606 // Replace the theme configs. 607 if (in_array(get_config('core', 'theme'), $themes)) { 608 set_config('theme', 'classic'); 609 } 610 if (in_array(get_config('core', 'thememobile'), $themes)) { 611 set_config('thememobile', 'classic'); 612 } 613 if (in_array(get_config('core', 'themelegacy'), $themes)) { 614 set_config('themelegacy', 'classic'); 615 } 616 if (in_array(get_config('core', 'themetablet'), $themes)) { 617 set_config('themetablet', 'classic'); 618 } 619 620 // Hacky emulation of plugin uninstallation. 621 foreach ($themes as $key => $theme) { 622 unset_all_config_for_plugin($key); 623 } 624 } 625 626 // Main savepoint reached. 627 upgrade_main_savepoint(true, 2019040200.01); 628 } 629 630 if ($oldversion < 2019040600.02) { 631 632 // Define key fileid (foreign) to be dropped form analytics_train_samples. 633 $table = new xmldb_table('analytics_train_samples'); 634 $key = new xmldb_key('fileid', XMLDB_KEY_FOREIGN, ['fileid'], 'files', ['id']); 635 636 // Launch drop key fileid. 637 $dbman->drop_key($table, $key); 638 639 // Define field fileid to be dropped from analytics_train_samples. 640 $table = new xmldb_table('analytics_train_samples'); 641 $field = new xmldb_field('fileid'); 642 643 // Conditionally launch drop field fileid. 644 if ($dbman->field_exists($table, $field)) { 645 $dbman->drop_field($table, $field); 646 } 647 648 // Main savepoint reached. 649 upgrade_main_savepoint(true, 2019040600.02); 650 } 651 652 if ($oldversion < 2019040600.04) { 653 // Define field and index to be added to backup_controllers. 654 $table = new xmldb_table('backup_controllers'); 655 $field = new xmldb_field('progress', XMLDB_TYPE_NUMBER, '15, 14', null, XMLDB_NOTNULL, null, '0', 'timemodified'); 656 $index = new xmldb_index('useritem_ix', XMLDB_INDEX_NOTUNIQUE, ['userid', 'itemid']); 657 // Conditionally launch add field progress. 658 if (!$dbman->field_exists($table, $field)) { 659 $dbman->add_field($table, $field); 660 } 661 // Conditionally launch add index useritem_ix. 662 if (!$dbman->index_exists($table, $index)) { 663 $dbman->add_index($table, $index); 664 } 665 666 // Main savepoint reached. 667 upgrade_main_savepoint(true, 2019040600.04); 668 } 669 670 if ($oldversion < 2019041000.02) { 671 672 // Define field fullmessagetrust to be added to messages. 673 $table = new xmldb_table('messages'); 674 $field = new xmldb_field('fullmessagetrust', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0', 'timecreated'); 675 676 // Conditionally launch add field fullmessagetrust. 677 if (!$dbman->field_exists($table, $field)) { 678 $dbman->add_field($table, $field); 679 } 680 681 // Main savepoint reached. 682 upgrade_main_savepoint(true, 2019041000.02); 683 } 684 685 if ($oldversion < 2019041300.01) { 686 // Add the field 'name' to the 'analytics_models' table. 687 $table = new xmldb_table('analytics_models'); 688 $field = new xmldb_field('name', XMLDB_TYPE_CHAR, '1333', null, null, null, null, 'trained'); 689 690 if (!$dbman->field_exists($table, $field)) { 691 $dbman->add_field($table, $field); 692 } 693 // Main savepoint reached. 694 upgrade_main_savepoint(true, 2019041300.01); 695 } 696 697 if ($oldversion < 2019041800.01) { 698 // STEP 1. For the existing and migrated self-conversations, set the type to the new MESSAGE_CONVERSATION_TYPE_SELF, update 699 // the convhash and star them. 700 $sql = "SELECT mcm.conversationid, mcm.userid, MAX(mcm.id) as maxid 701 FROM {message_conversation_members} mcm 702 INNER JOIN {user} u ON mcm.userid = u.id 703 WHERE u.deleted = 0 704 GROUP BY mcm.conversationid, mcm.userid 705 HAVING COUNT(*) > 1"; 706 $selfconversationsrs = $DB->get_recordset_sql($sql); 707 $maxids = []; 708 foreach ($selfconversationsrs as $selfconversation) { 709 $DB->update_record('message_conversations', 710 ['id' => $selfconversation->conversationid, 711 'type' => \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, 712 'convhash' => \core_message\helper::get_conversation_hash([$selfconversation->userid]) 713 ] 714 ); 715 716 // Star the existing self-conversation. 717 $favouriterecord = new \stdClass(); 718 $favouriterecord->component = 'core_message'; 719 $favouriterecord->itemtype = 'message_conversations'; 720 $favouriterecord->itemid = $selfconversation->conversationid; 721 $userctx = \context_user::instance($selfconversation->userid); 722 $favouriterecord->contextid = $userctx->id; 723 $favouriterecord->userid = $selfconversation->userid; 724 if (!$DB->record_exists('favourite', (array)$favouriterecord)) { 725 $favouriterecord->timecreated = time(); 726 $favouriterecord->timemodified = $favouriterecord->timecreated; 727 $DB->insert_record('favourite', $favouriterecord); 728 } 729 730 // Set the self-conversation member with maxid to remove it later. 731 $maxids[] = $selfconversation->maxid; 732 } 733 $selfconversationsrs->close(); 734 735 // Remove the repeated member with the higher id for all the existing self-conversations. 736 if (!empty($maxids)) { 737 list($insql, $inparams) = $DB->get_in_or_equal($maxids); 738 $DB->delete_records_select('message_conversation_members', "id $insql", $inparams); 739 } 740 741 // STEP 2. Migrate existing self-conversation relying on old message tables, setting the type to the new 742 // MESSAGE_CONVERSATION_TYPE_SELF and the convhash to the proper one. Star them also. 743 744 // On the messaging legacy tables, self-conversations are only present in the 'message_read' table, so we don't need to 745 // check the content in the 'message' table. 746 $sql = "SELECT mr.* 747 FROM {message_read} mr 748 INNER JOIN {user} u ON mr.useridfrom = u.id 749 WHERE mr.useridfrom = mr.useridto AND mr.notification = 0 AND u.deleted = 0"; 750 $legacyselfmessagesrs = $DB->get_recordset_sql($sql); 751 foreach ($legacyselfmessagesrs as $message) { 752 // Get the self-conversation or create and star it if doesn't exist. 753 $conditions = [ 754 'type' => \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF, 755 'convhash' => \core_message\helper::get_conversation_hash([$message->useridfrom]) 756 ]; 757 $selfconversation = $DB->get_record('message_conversations', $conditions); 758 if (empty($selfconversation)) { 759 // Create the self-conversation. 760 $selfconversation = new \stdClass(); 761 $selfconversation->type = \core_message\api::MESSAGE_CONVERSATION_TYPE_SELF; 762 $selfconversation->convhash = \core_message\helper::get_conversation_hash([$message->useridfrom]); 763 $selfconversation->enabled = 1; 764 $selfconversation->timecreated = time(); 765 $selfconversation->timemodified = $selfconversation->timecreated; 766 767 $selfconversation->id = $DB->insert_record('message_conversations', $selfconversation); 768 769 // Add user to this self-conversation. 770 $member = new \stdClass(); 771 $member->conversationid = $selfconversation->id; 772 $member->userid = $message->useridfrom; 773 $member->timecreated = time(); 774 775 $member->id = $DB->insert_record('message_conversation_members', $member); 776 777 // Star the self-conversation. 778 $favouriterecord = new \stdClass(); 779 $favouriterecord->component = 'core_message'; 780 $favouriterecord->itemtype = 'message_conversations'; 781 $favouriterecord->itemid = $selfconversation->id; 782 $userctx = \context_user::instance($message->useridfrom); 783 $favouriterecord->contextid = $userctx->id; 784 $favouriterecord->userid = $message->useridfrom; 785 if (!$DB->record_exists('favourite', (array)$favouriterecord)) { 786 $favouriterecord->timecreated = time(); 787 $favouriterecord->timemodified = $favouriterecord->timecreated; 788 $DB->insert_record('favourite', $favouriterecord); 789 } 790 } 791 792 // Create the object we will be inserting into the database. 793 $tabledata = new \stdClass(); 794 $tabledata->useridfrom = $message->useridfrom; 795 $tabledata->conversationid = $selfconversation->id; 796 $tabledata->subject = $message->subject; 797 $tabledata->fullmessage = $message->fullmessage; 798 $tabledata->fullmessageformat = $message->fullmessageformat ?? FORMAT_MOODLE; 799 $tabledata->fullmessagehtml = $message->fullmessagehtml; 800 $tabledata->smallmessage = $message->smallmessage; 801 $tabledata->timecreated = $message->timecreated; 802 803 $messageid = $DB->insert_record('messages', $tabledata); 804 805 // Check if we need to mark this message as deleted (self-conversations add this information on the 806 // timeuserfromdeleted field. 807 if ($message->timeuserfromdeleted) { 808 $mua = new \stdClass(); 809 $mua->userid = $message->useridfrom; 810 $mua->messageid = $messageid; 811 $mua->action = \core_message\api::MESSAGE_ACTION_DELETED; 812 $mua->timecreated = $message->timeuserfromdeleted; 813 814 $DB->insert_record('message_user_actions', $mua); 815 } 816 817 // Mark this message as read. 818 $mua = new \stdClass(); 819 $mua->userid = $message->useridto; 820 $mua->messageid = $messageid; 821 $mua->action = \core_message\api::MESSAGE_ACTION_READ; 822 $mua->timecreated = $message->timeread; 823 824 $DB->insert_record('message_user_actions', $mua); 825 826 // The self-conversation message has been migrated. Delete the record from the legacy table as soon as possible 827 // to avoid migrate it twice. 828 $DB->delete_records('message_read', ['id' => $message->id]); 829 } 830 $legacyselfmessagesrs->close(); 831 832 // Main savepoint reached. 833 upgrade_main_savepoint(true, 2019041800.01); 834 } 835 836 if ($oldversion < 2019042200.01) { 837 838 // Define table role_sortorder to be dropped. 839 $table = new xmldb_table('role_sortorder'); 840 841 // Conditionally launch drop table for role_sortorder. 842 if ($dbman->table_exists($table)) { 843 $dbman->drop_table($table); 844 } 845 846 // Main savepoint reached. 847 upgrade_main_savepoint(true, 2019042200.01); 848 } 849 850 if ($oldversion < 2019042200.02) { 851 852 // Let's update all (old core) targets to their new (core_course) locations. 853 $targets = [ 854 '\core\analytics\target\course_competencies' => '\core_course\analytics\target\course_competencies', 855 '\core\analytics\target\course_completion' => '\core_course\analytics\target\course_completion', 856 '\core\analytics\target\course_dropout' => '\core_course\analytics\target\course_dropout', 857 '\core\analytics\target\course_gradetopass' => '\core_course\analytics\target\course_gradetopass', 858 '\core\analytics\target\no_teaching' => '\core_course\analytics\target\no_teaching', 859 ]; 860 861 foreach ($targets as $oldclass => $newclass) { 862 $DB->set_field('analytics_models', 'target', $newclass, ['target' => $oldclass]); 863 } 864 865 // Main savepoint reached. 866 upgrade_main_savepoint(true, 2019042200.02); 867 } 868 869 if ($oldversion < 2019042300.01) { 870 $sql = "UPDATE {capabilities} 871 SET name = ?, 872 contextlevel = ? 873 WHERE name = ?"; 874 $DB->execute($sql, ['moodle/category:viewcourselist', CONTEXT_COURSECAT, 'moodle/course:browse']); 875 876 $sql = "UPDATE {role_capabilities} 877 SET capability = ? 878 WHERE capability = ?"; 879 $DB->execute($sql, ['moodle/category:viewcourselist', 'moodle/course:browse']); 880 881 // Main savepoint reached. 882 upgrade_main_savepoint(true, 2019042300.01); 883 } 884 885 if ($oldversion < 2019042300.03) { 886 887 // Add new customdata field to message table. 888 $table = new xmldb_table('message'); 889 $field = new xmldb_field('customdata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'eventtype'); 890 891 // Conditionally launch add field output. 892 if (!$dbman->field_exists($table, $field)) { 893 $dbman->add_field($table, $field); 894 } 895 896 // Add new customdata field to notifications and messages table. 897 $table = new xmldb_table('notifications'); 898 $field = new xmldb_field('customdata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'timecreated'); 899 900 // Conditionally launch add field output. 901 if (!$dbman->field_exists($table, $field)) { 902 $dbman->add_field($table, $field); 903 } 904 905 $table = new xmldb_table('messages'); 906 // Conditionally launch add field output. 907 if (!$dbman->field_exists($table, $field)) { 908 $dbman->add_field($table, $field); 909 } 910 911 // Main savepoint reached. 912 upgrade_main_savepoint(true, 2019042300.03); 913 } 914 915 if ($oldversion < 2019042700.01) { 916 917 // Define field firstanalysis to be added to analytics_used_analysables. 918 $table = new xmldb_table('analytics_used_analysables'); 919 920 // Declaring it as null initially (although it is NOT NULL). 921 $field = new xmldb_field('firstanalysis', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'analysableid'); 922 923 // Conditionally launch add field firstanalysis. 924 if (!$dbman->field_exists($table, $field)) { 925 $dbman->add_field($table, $field); 926 927 // Set existing values to the current timeanalysed value. 928 $recordset = $DB->get_recordset('analytics_used_analysables'); 929 foreach ($recordset as $record) { 930 $record->firstanalysis = $record->timeanalysed; 931 $DB->update_record('analytics_used_analysables', $record); 932 } 933 $recordset->close(); 934 935 // Now make the field 'NOT NULL'. 936 $field = new xmldb_field('firstanalysis', XMLDB_TYPE_INTEGER, '10', 937 null, XMLDB_NOTNULL, null, null, 'analysableid'); 938 $dbman->change_field_notnull($table, $field); 939 } 940 941 // Main savepoint reached. 942 upgrade_main_savepoint(true, 2019042700.01); 943 } 944 945 if ($oldversion < 2019050300.01) { 946 // Delete all stale favourite records which were left behind when a course was deleted. 947 $params = ['component' => 'core_message', 'itemtype' => 'message_conversations']; 948 $sql = "SELECT fav.id as id 949 FROM {favourite} fav 950 LEFT JOIN {context} ctx ON (ctx.id = fav.contextid) 951 WHERE fav.component = :component 952 AND fav.itemtype = :itemtype 953 AND ctx.id IS NULL"; 954 955 if ($records = $DB->get_fieldset_sql($sql, $params)) { 956 // Just for safety, delete by chunks. 957 $chunks = array_chunk($records, 1000); 958 foreach ($chunks as $chunk) { 959 list($insql, $inparams) = $DB->get_in_or_equal($chunk); 960 $DB->delete_records_select('favourite', "id $insql", $inparams); 961 } 962 } 963 964 upgrade_main_savepoint(true, 2019050300.01); 965 } 966 967 if ($oldversion < 2019050600.00) { 968 969 // Define field apiversion to be added to badge_backpack. 970 $table = new xmldb_table('badge_backpack'); 971 $field = new xmldb_field('apiversion', XMLDB_TYPE_CHAR, '12', null, XMLDB_NOTNULL, null, '1.0', 'password'); 972 973 // Conditionally launch add field apiversion. 974 if (!$dbman->field_exists($table, $field)) { 975 $dbman->add_field($table, $field); 976 } 977 978 // Define table badge_external_backpack to be created. 979 $table = new xmldb_table('badge_external_backpack'); 980 981 // Adding fields to table badge_external_backpack. 982 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 983 $table->add_field('backpackapiurl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 984 $table->add_field('backpackweburl', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 985 $table->add_field('apiversion', XMLDB_TYPE_CHAR, '12', null, XMLDB_NOTNULL, null, '1.0'); 986 $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 987 $table->add_field('password', XMLDB_TYPE_CHAR, '255', null, null, null, null); 988 989 // Adding keys to table badge_external_backpack. 990 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 991 $table->add_key('backpackapiurlkey', XMLDB_KEY_UNIQUE, ['backpackapiurl']); 992 $table->add_key('backpackweburlkey', XMLDB_KEY_UNIQUE, ['backpackweburl']); 993 994 // Conditionally launch create table for badge_external_backpack. 995 if (!$dbman->table_exists($table)) { 996 $dbman->create_table($table); 997 } 998 999 // Define field entityid to be added to badge_external. 1000 $table = new xmldb_table('badge_external'); 1001 $field = new xmldb_field('entityid', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'collectionid'); 1002 1003 // Conditionally launch add field entityid. 1004 if (!$dbman->field_exists($table, $field)) { 1005 $dbman->add_field($table, $field); 1006 } 1007 1008 // Define table badge_external_identifier to be created. 1009 $table = new xmldb_table('badge_external_identifier'); 1010 1011 // Adding fields to table badge_external_identifier. 1012 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1013 $table->add_field('sitebackpackid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1014 $table->add_field('internalid', XMLDB_TYPE_CHAR, '128', null, XMLDB_NOTNULL, null, null); 1015 $table->add_field('externalid', XMLDB_TYPE_CHAR, '128', null, XMLDB_NOTNULL, null, null); 1016 $table->add_field('type', XMLDB_TYPE_CHAR, '16', null, XMLDB_NOTNULL, null, null); 1017 1018 // Adding keys to table badge_external_identifier. 1019 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 1020 $table->add_key('fk_backpackid', XMLDB_KEY_FOREIGN, ['sitebackpackid'], 'badge_backpack', ['id']); 1021 $table->add_key('backpack-internal-external', XMLDB_KEY_UNIQUE, ['sitebackpackid', 'internalid', 'externalid', 'type']); 1022 1023 // Conditionally launch create table for badge_external_identifier. 1024 if (!$dbman->table_exists($table)) { 1025 $dbman->create_table($table); 1026 } 1027 1028 // Define field externalbackpackid to be added to badge_backpack. 1029 $table = new xmldb_table('badge_backpack'); 1030 $field = new xmldb_field('externalbackpackid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'password'); 1031 1032 // Conditionally launch add field externalbackpackid. 1033 if (!$dbman->field_exists($table, $field)) { 1034 $dbman->add_field($table, $field); 1035 } 1036 1037 // Define key externalbackpack (foreign) to be added to badge_backpack. 1038 $key = new xmldb_key('externalbackpack', XMLDB_KEY_FOREIGN, ['externalbackpackid'], 'badge_external_backpack', ['id']); 1039 1040 // Launch add key externalbackpack. 1041 $dbman->add_key($table, $key); 1042 1043 $field = new xmldb_field('apiversion'); 1044 1045 // Conditionally launch drop field apiversion. 1046 if ($dbman->field_exists($table, $field)) { 1047 $dbman->drop_field($table, $field); 1048 } 1049 1050 $field = new xmldb_field('backpackurl'); 1051 1052 // Conditionally launch drop field backpackurl. 1053 if ($dbman->field_exists($table, $field)) { 1054 $dbman->drop_field($table, $field); 1055 } 1056 1057 // Add default backpacks. 1058 require_once($CFG->dirroot . '/badges/upgradelib.php'); // Core install and upgrade related functions only for badges. 1059 badges_install_default_backpacks(); 1060 1061 // Main savepoint reached. 1062 upgrade_main_savepoint(true, 2019050600.00); 1063 } 1064 1065 if ($oldversion < 2019051300.01) { 1066 $DB->set_field('analytics_models', 'enabled', '1', ['target' => '\core_user\analytics\target\upcoming_activities_due']); 1067 1068 // Main savepoint reached. 1069 upgrade_main_savepoint(true, 2019051300.01); 1070 } 1071 1072 // Automatically generated Moodle v3.7.0 release upgrade line. 1073 // Put any upgrade step following this. 1074 1075 if ($oldversion < 2019060600.02) { 1076 // Renaming 'opentogoogle' config to 'opentowebcrawlers'. 1077 $opentogooglevalue = get_config('core', 'opentogoogle'); 1078 1079 // Move the value over if it was previously configured. 1080 if ($opentogooglevalue !== false) { 1081 set_config('opentowebcrawlers', $opentogooglevalue); 1082 } 1083 1084 // Remove the now unused value. 1085 unset_config('opentogoogle'); 1086 1087 // Main savepoint reached. 1088 upgrade_main_savepoint(true, 2019060600.02); 1089 } 1090 1091 if ($oldversion < 2019062900.00) { 1092 // Debugsmtp is now only available via config.php. 1093 $DB->delete_records('config', array('name' => 'debugsmtp')); 1094 1095 // Main savepoint reached. 1096 upgrade_main_savepoint(true, 2019062900.00); 1097 } 1098 1099 if ($oldversion < 2019070400.01) { 1100 1101 $basecolors = ['#81ecec', '#74b9ff', '#a29bfe', '#dfe6e9', '#00b894', 1102 '#0984e3', '#b2bec3', '#fdcb6e', '#fd79a8', '#6c5ce7']; 1103 1104 $colornr = 1; 1105 foreach ($basecolors as $color) { 1106 set_config('coursecolor' . $colornr, $color, 'core_admin'); 1107 $colornr++; 1108 } 1109 1110 upgrade_main_savepoint(true, 2019070400.01); 1111 } 1112 1113 if ($oldversion < 2019072200.00) { 1114 1115 // Define field relativedatesmode to be added to course. 1116 $table = new xmldb_table('course'); 1117 $field = new xmldb_field('relativedatesmode', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'enddate'); 1118 1119 // Conditionally launch add field relativedatesmode. 1120 if (!$dbman->field_exists($table, $field)) { 1121 $dbman->add_field($table, $field); 1122 } 1123 1124 // Main savepoint reached. 1125 upgrade_main_savepoint(true, 2019072200.00); 1126 } 1127 1128 if ($oldversion < 2019072500.01) { 1129 // Remove the "popup" processor from the list of default processors for the messagecontactrequests notification. 1130 $oldloggedinconfig = get_config('message', 'message_provider_moodle_messagecontactrequests_loggedin'); 1131 $oldloggedoffconfig = get_config('message', 'message_provider_moodle_messagecontactrequests_loggedoff'); 1132 $newloggedinconfig = implode(',', array_filter(explode(',', $oldloggedinconfig), function($value) { 1133 return $value != 'popup'; 1134 })); 1135 $newloggedoffconfig = implode(',', array_filter(explode(',', $oldloggedoffconfig), function($value) { 1136 return $value != 'popup'; 1137 })); 1138 set_config('message_provider_moodle_messagecontactrequests_loggedin', $newloggedinconfig, 'message'); 1139 set_config('message_provider_moodle_messagecontactrequests_loggedoff', $newloggedoffconfig, 'message'); 1140 1141 upgrade_main_savepoint(true, 2019072500.01); 1142 } 1143 1144 if ($oldversion < 2019072500.03) { 1145 unset_config('httpswwwroot'); 1146 1147 upgrade_main_savepoint(true, 2019072500.03); 1148 } 1149 1150 if ($oldversion < 2019073100.00) { 1151 // Update the empty tag instructions to null. 1152 $instructions = get_config('core', 'auth_instructions'); 1153 1154 if (trim(html_to_text($instructions)) === '') { 1155 set_config('auth_instructions', ''); 1156 } 1157 1158 // Main savepoint reached. 1159 upgrade_main_savepoint(true, 2019073100.00); 1160 } 1161 1162 if ($oldversion < 2019083000.01) { 1163 1164 // If block_community is no longer present, remove it. 1165 if (!file_exists($CFG->dirroot . '/blocks/community/communitycourse.php')) { 1166 // Drop table that is no longer needed. 1167 $table = new xmldb_table('block_community'); 1168 if ($dbman->table_exists($table)) { 1169 $dbman->drop_table($table); 1170 } 1171 1172 // Delete instances. 1173 $instances = $DB->get_records_list('block_instances', 'blockname', ['community']); 1174 $instanceids = array_keys($instances); 1175 1176 if (!empty($instanceids)) { 1177 $DB->delete_records_list('block_positions', 'blockinstanceid', $instanceids); 1178 $DB->delete_records_list('block_instances', 'id', $instanceids); 1179 list($sql, $params) = $DB->get_in_or_equal($instanceids, SQL_PARAMS_NAMED); 1180 $params['contextlevel'] = CONTEXT_BLOCK; 1181 $DB->delete_records_select('context', "contextlevel=:contextlevel AND instanceid " . $sql, $params); 1182 1183 $preferences = array(); 1184 foreach ($instances as $instanceid => $instance) { 1185 $preferences[] = 'block' . $instanceid . 'hidden'; 1186 $preferences[] = 'docked_block_instance_' . $instanceid; 1187 } 1188 $DB->delete_records_list('user_preferences', 'name', $preferences); 1189 } 1190 1191 // Delete the block from the block table. 1192 $DB->delete_records('block', array('name' => 'community')); 1193 1194 // Remove capabilities. 1195 capabilities_cleanup('block_community'); 1196 // Clean config. 1197 unset_all_config_for_plugin('block_community'); 1198 1199 // Remove Moodle-level community based capabilities. 1200 $capabilitiestoberemoved = ['block/community:addinstance', 'block/community:myaddinstance']; 1201 // Delete any role_capabilities for the old roles. 1202 $DB->delete_records_list('role_capabilities', 'capability', $capabilitiestoberemoved); 1203 // Delete the capability itself. 1204 $DB->delete_records_list('capabilities', 'name', $capabilitiestoberemoved); 1205 } 1206 1207 upgrade_main_savepoint(true, 2019083000.01); 1208 } 1209 1210 if ($oldversion < 2019083000.02) { 1211 // Remove unused config. 1212 unset_config('enablecoursepublishing'); 1213 upgrade_main_savepoint(true, 2019083000.02); 1214 } 1215 1216 if ($oldversion < 2019083000.04) { 1217 // Delete "orphaned" subscriptions. 1218 $sql = "SELECT DISTINCT es.userid 1219 FROM {event_subscriptions} es 1220 LEFT JOIN {user} u ON u.id = es.userid 1221 WHERE u.deleted = 1 OR u.id IS NULL"; 1222 $deletedusers = $DB->get_fieldset_sql($sql); 1223 if ($deletedusers) { 1224 list($sql, $params) = $DB->get_in_or_equal($deletedusers); 1225 1226 // Delete orphaned subscriptions. 1227 $DB->execute("DELETE FROM {event_subscriptions} WHERE userid " . $sql, $params); 1228 } 1229 1230 upgrade_main_savepoint(true, 2019083000.04); 1231 } 1232 1233 if ($oldversion < 2019090500.01) { 1234 1235 // Define index analysableid (not unique) to be added to analytics_used_analysables. 1236 $table = new xmldb_table('analytics_used_analysables'); 1237 $index = new xmldb_index('analysableid', XMLDB_INDEX_NOTUNIQUE, ['analysableid']); 1238 1239 // Conditionally launch add index analysableid. 1240 if (!$dbman->index_exists($table, $index)) { 1241 $dbman->add_index($table, $index); 1242 } 1243 1244 // Main savepoint reached. 1245 upgrade_main_savepoint(true, 2019090500.01); 1246 } 1247 1248 if ($oldversion < 2019092700.01) { 1249 upgrade_rename_prediction_actions_useful_incorrectly_flagged(); 1250 upgrade_main_savepoint(true, 2019092700.01); 1251 } 1252 1253 if ($oldversion < 2019100800.02) { 1254 // Rename the official moodle sites directory the site is registered with. 1255 $DB->execute("UPDATE {registration_hubs} 1256 SET hubname = ?, huburl = ? 1257 WHERE huburl = ?", ['moodle', 'https://stats.moodle.org', 'https://moodle.net']); 1258 1259 // Convert the hub site specific settings to the new naming format without the hub URL in the name. 1260 $hubconfig = get_config('hub'); 1261 1262 if (!empty($hubconfig)) { 1263 foreach (upgrade_convert_hub_config_site_param_names($hubconfig, 'https://moodle.net') as $name => $value) { 1264 set_config($name, $value, 'hub'); 1265 } 1266 } 1267 1268 upgrade_main_savepoint(true, 2019100800.02); 1269 } 1270 1271 if ($oldversion < 2019100900.00) { 1272 // If block_participants is no longer present, remove it. 1273 if (!file_exists($CFG->dirroot . '/blocks/participants/block_participants.php')) { 1274 // Delete instances. 1275 $instances = $DB->get_records_list('block_instances', 'blockname', ['participants']); 1276 $instanceids = array_keys($instances); 1277 1278 if (!empty($instanceids)) { 1279 $DB->delete_records_list('block_positions', 'blockinstanceid', $instanceids); 1280 $DB->delete_records_list('block_instances', 'id', $instanceids); 1281 list($sql, $params) = $DB->get_in_or_equal($instanceids, SQL_PARAMS_NAMED); 1282 $params['contextlevel'] = CONTEXT_BLOCK; 1283 $DB->delete_records_select('context', "contextlevel=:contextlevel AND instanceid " . $sql, $params); 1284 1285 $preferences = array(); 1286 foreach ($instances as $instanceid => $instance) { 1287 $preferences[] = 'block' . $instanceid . 'hidden'; 1288 $preferences[] = 'docked_block_instance_' . $instanceid; 1289 } 1290 $DB->delete_records_list('user_preferences', 'name', $preferences); 1291 } 1292 1293 // Delete the block from the block table. 1294 $DB->delete_records('block', array('name' => 'participants')); 1295 1296 // Remove capabilities. 1297 capabilities_cleanup('block_participants'); 1298 1299 // Clean config. 1300 unset_all_config_for_plugin('block_participants'); 1301 } 1302 1303 upgrade_main_savepoint(true, 2019100900.00); 1304 } 1305 1306 if ($oldversion < 2019101600.01) { 1307 1308 // Change the setting $CFG->requestcategoryselection into $CFG->lockrequestcategory with opposite value. 1309 set_config('lockrequestcategory', empty($CFG->requestcategoryselection)); 1310 1311 upgrade_main_savepoint(true, 2019101600.01); 1312 } 1313 1314 if ($oldversion < 2019101800.02) { 1315 1316 // Get the table by its previous name. 1317 $table = new xmldb_table('analytics_models'); 1318 if ($dbman->table_exists($table)) { 1319 1320 // Define field contextids to be added to analytics_models. 1321 $field = new xmldb_field('contextids', XMLDB_TYPE_TEXT, null, null, null, null, null, 'version'); 1322 1323 // Conditionally launch add field contextids. 1324 if (!$dbman->field_exists($table, $field)) { 1325 $dbman->add_field($table, $field); 1326 } 1327 } 1328 1329 // Main savepoint reached. 1330 upgrade_main_savepoint(true, 2019101800.02); 1331 } 1332 1333 if ($oldversion < 2019102500.04) { 1334 // Define table h5p_libraries to be created. 1335 $table = new xmldb_table('h5p_libraries'); 1336 1337 // Adding fields to table h5p_libraries. 1338 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1339 $table->add_field('machinename', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 1340 $table->add_field('title', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 1341 $table->add_field('majorversion', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null); 1342 $table->add_field('minorversion', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null); 1343 $table->add_field('patchversion', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, null); 1344 $table->add_field('runnable', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null); 1345 $table->add_field('fullscreen', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 1346 $table->add_field('embedtypes', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 1347 $table->add_field('preloadedjs', XMLDB_TYPE_TEXT, null, null, null, null, null); 1348 $table->add_field('preloadedcss', XMLDB_TYPE_TEXT, null, null, null, null, null); 1349 $table->add_field('droplibrarycss', XMLDB_TYPE_TEXT, null, null, null, null, null); 1350 $table->add_field('semantics', XMLDB_TYPE_TEXT, null, null, null, null, null); 1351 $table->add_field('addto', XMLDB_TYPE_TEXT, null, null, null, null, null); 1352 1353 // Adding keys to table h5p_libraries. 1354 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 1355 1356 // Adding indexes to table h5p_libraries. 1357 $table->add_index('machinemajorminorpatch', XMLDB_INDEX_NOTUNIQUE, 1358 ['machinename', 'majorversion', 'minorversion', 'patchversion', 'runnable']); 1359 1360 // Conditionally launch create table for h5p_libraries. 1361 if (!$dbman->table_exists($table)) { 1362 $dbman->create_table($table); 1363 } 1364 1365 // Define table h5p_library_dependencies to be created. 1366 $table = new xmldb_table('h5p_library_dependencies'); 1367 1368 // Adding fields to table h5p_library_dependencies. 1369 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1370 $table->add_field('libraryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1371 $table->add_field('requiredlibraryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1372 $table->add_field('dependencytype', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 1373 1374 // Adding keys to table h5p_library_dependencies. 1375 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 1376 $table->add_key('libraryid', XMLDB_KEY_FOREIGN, ['libraryid'], 'h5p_libraries', ['id']); 1377 $table->add_key('requiredlibraryid', XMLDB_KEY_FOREIGN, ['requiredlibraryid'], 'h5p_libraries', ['id']); 1378 1379 // Conditionally launch create table for h5p_library_dependencies. 1380 if (!$dbman->table_exists($table)) { 1381 $dbman->create_table($table); 1382 } 1383 1384 // Define table h5p to be created. 1385 $table = new xmldb_table('h5p'); 1386 1387 // Adding fields to table h5p. 1388 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1389 $table->add_field('jsoncontent', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); 1390 $table->add_field('mainlibraryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1391 $table->add_field('displayoptions', XMLDB_TYPE_INTEGER, '4', null, null, null, null); 1392 $table->add_field('pathnamehash', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null); 1393 $table->add_field('contenthash', XMLDB_TYPE_CHAR, '40', null, XMLDB_NOTNULL, null, null); 1394 $table->add_field('filtered', XMLDB_TYPE_TEXT, null, null, null, null, null); 1395 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1396 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1397 1398 // Adding keys to table h5p. 1399 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 1400 $table->add_key('mainlibraryid', XMLDB_KEY_FOREIGN, ['mainlibraryid'], 'h5p_libraries', ['id']); 1401 1402 // Conditionally launch create table for h5p. 1403 if (!$dbman->table_exists($table)) { 1404 $dbman->create_table($table); 1405 } 1406 1407 // Define table h5p_contents_libraries to be created. 1408 $table = new xmldb_table('h5p_contents_libraries'); 1409 1410 // Adding fields to table h5p_contents_libraries. 1411 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1412 $table->add_field('h5pid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1413 $table->add_field('libraryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1414 $table->add_field('dependencytype', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, null); 1415 $table->add_field('dropcss', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null); 1416 $table->add_field('weight', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1417 1418 // Adding keys to table h5p_contents_libraries. 1419 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 1420 $table->add_key('h5pid', XMLDB_KEY_FOREIGN, ['h5pid'], 'h5p', ['id']); 1421 $table->add_key('libraryid', XMLDB_KEY_FOREIGN, ['libraryid'], 'h5p_libraries', ['id']); 1422 1423 // Conditionally launch create table for h5p_contents_libraries. 1424 if (!$dbman->table_exists($table)) { 1425 $dbman->create_table($table); 1426 } 1427 1428 // Define table h5p_libraries_cachedassets to be created. 1429 $table = new xmldb_table('h5p_libraries_cachedassets'); 1430 1431 // Adding fields to table h5p_libraries_cachedassets. 1432 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1433 $table->add_field('libraryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1434 $table->add_field('hash', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 1435 1436 // Adding keys to table h5p_libraries_cachedassets. 1437 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 1438 $table->add_key('libraryid', XMLDB_KEY_FOREIGN, ['libraryid'], 'h5p_libraries_cachedassets', ['id']); 1439 1440 // Conditionally launch create table for h5p_libraries_cachedassets. 1441 if (!$dbman->table_exists($table)) { 1442 $dbman->create_table($table); 1443 } 1444 1445 // Main savepoint reached. 1446 upgrade_main_savepoint(true, 2019102500.04); 1447 } 1448 1449 if ($oldversion < 2019103000.13) { 1450 1451 upgrade_analytics_fix_contextids_defaults(); 1452 1453 // Main savepoint reached. 1454 upgrade_main_savepoint(true, 2019103000.13); 1455 } 1456 1457 if ($oldversion < 2019111300.00) { 1458 1459 // Define field coremajor to be added to h5p_libraries. 1460 $table = new xmldb_table('h5p_libraries'); 1461 $field = new xmldb_field('coremajor', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'addto'); 1462 1463 // Conditionally launch add field coremajor. 1464 if (!$dbman->field_exists($table, $field)) { 1465 $dbman->add_field($table, $field); 1466 } 1467 1468 $field = new xmldb_field('coreminor', XMLDB_TYPE_INTEGER, '4', null, null, null, null, 'coremajor'); 1469 1470 // Conditionally launch add field coreminor. 1471 if (!$dbman->field_exists($table, $field)) { 1472 $dbman->add_field($table, $field); 1473 } 1474 1475 // Main savepoint reached. 1476 upgrade_main_savepoint(true, 2019111300.00); 1477 } 1478 1479 // Automatically generated Moodle v3.8.0 release upgrade line. 1480 // Put any upgrade step following this. 1481 1482 if ($oldversion < 2019120500.01) { 1483 // Delete any role assignments for roles which no longer exist. 1484 $DB->delete_records_select('role_assignments', "roleid NOT IN (SELECT id FROM {role})"); 1485 1486 // Main savepoint reached. 1487 upgrade_main_savepoint(true, 2019120500.01); 1488 } 1489 1490 if ($oldversion < 2019121800.00) { 1491 // Upgrade MIME types for existing streaming files. 1492 $filetypes = array( 1493 '%.fmp4' => 'video/mp4', 1494 '%.ts' => 'video/MP2T', 1495 '%.mpd' => 'application/dash+xml', 1496 '%.m3u8' => 'application/x-mpegURL', 1497 ); 1498 1499 $select = $DB->sql_like('filename', '?', false); 1500 foreach ($filetypes as $extension => $mimetype) { 1501 $DB->set_field_select( 1502 'files', 1503 'mimetype', 1504 $mimetype, 1505 $select, 1506 array($extension) 1507 ); 1508 } 1509 1510 upgrade_main_savepoint(true, 2019121800.00); 1511 } 1512 1513 if ($oldversion < 2019122000.01) { 1514 // Clean old upgrade setting not used anymore. 1515 unset_config('linkcoursesectionsupgradescriptwasrun'); 1516 upgrade_main_savepoint(true, 2019122000.01); 1517 } 1518 1519 if ($oldversion < 2020010900.02) { 1520 $table = new xmldb_table('event'); 1521 1522 // This index will improve the performance when the Events API retrieves category and group events. 1523 $index = new xmldb_index('eventtype', XMLDB_INDEX_NOTUNIQUE, ['eventtype']); 1524 if (!$dbman->index_exists($table, $index)) { 1525 $dbman->add_index($table, $index); 1526 } 1527 1528 // This index improves the performance of backups, deletion and visibilty changes on activities. 1529 $index = new xmldb_index('modulename-instance', XMLDB_INDEX_NOTUNIQUE, ['modulename', 'instance']); 1530 if (!$dbman->index_exists($table, $index)) { 1531 $dbman->add_index($table, $index); 1532 } 1533 1534 upgrade_main_savepoint(true, 2020010900.02); 1535 } 1536 1537 if ($oldversion < 2020011700.02) { 1538 // Delete all orphaned subscription events. 1539 $select = "subscriptionid IS NOT NULL 1540 AND subscriptionid NOT IN (SELECT id from {event_subscriptions})"; 1541 $DB->delete_records_select('event', $select); 1542 1543 upgrade_main_savepoint(true, 2020011700.02); 1544 } 1545 1546 if ($oldversion < 2020013000.01) { 1547 global $DB; 1548 // Delete any associated files. 1549 $fs = get_file_storage(); 1550 $sql = "SELECT cuc.id, cuc.userid 1551 FROM {competency_usercomp} cuc 1552 LEFT JOIN {user} u ON cuc.userid = u.id 1553 WHERE u.deleted = 1"; 1554 $usercompetencies = $DB->get_records_sql($sql); 1555 foreach ($usercompetencies as $usercomp) { 1556 $DB->delete_records('competency_evidence', ['usercompetencyid' => $usercomp->id]); 1557 $DB->delete_records('competency_usercompcourse', ['userid' => $usercomp->userid]); 1558 $DB->delete_records('competency_usercompplan', ['userid' => $usercomp->userid]); 1559 $DB->delete_records('competency_usercomp', ['userid' => $usercomp->userid]); 1560 } 1561 1562 $sql = "SELECT cue.id, cue.userid 1563 FROM {competency_userevidence} cue 1564 LEFT JOIN {user} u ON cue.userid = u.id 1565 WHERE u.deleted = 1"; 1566 $userevidences = $DB->get_records_sql($sql); 1567 foreach ($userevidences as $userevidence) { 1568 $DB->delete_records('competency_userevidencecomp', ['userevidenceid' => $userevidence->id]); 1569 $DB->delete_records('competency_userevidence', ['id' => $userevidence->id]); 1570 1571 if ($record = $DB->get_record('context', ['contextlevel' => CONTEXT_USER, 'instanceid' => $userevidence->userid], 1572 '*', IGNORE_MISSING)) { 1573 // Delete all orphaned user evidences files. 1574 $fs->delete_area_files($record->id, 'core_competency', 'userevidence', $userevidence->userid); 1575 } 1576 } 1577 1578 $sql = "SELECT cp.id 1579 FROM {competency_plan} cp 1580 LEFT JOIN {user} u ON cp.userid = u.id 1581 WHERE u.deleted = 1"; 1582 $userplans = $DB->get_records_sql($sql); 1583 foreach ($userplans as $userplan) { 1584 $DB->delete_records('competency_plancomp', ['planid' => $userplan->id]); 1585 $DB->delete_records('competency_plan', ['id' => $userplan->id]); 1586 } 1587 1588 // Main savepoint reached. 1589 upgrade_main_savepoint(true, 2020013000.01); 1590 } 1591 1592 if ($oldversion < 2020040200.01) { 1593 // Clean up completion criteria records referring to courses that no longer exist. 1594 $select = 'criteriatype = :type AND courseinstance NOT IN (SELECT id FROM {course})'; 1595 $params = ['type' => 8]; // COMPLETION_CRITERIA_TYPE_COURSE. 1596 1597 $DB->delete_records_select('course_completion_criteria', $select, $params); 1598 1599 // Main savepoint reached. 1600 upgrade_main_savepoint(true, 2020040200.01); 1601 } 1602 1603 if ($oldversion < 2020040700.00) { 1604 // Remove deprecated Mozilla OpenBadges backpack. 1605 $url = 'https://backpack.openbadges.org'; 1606 $bp = $DB->get_record('badge_external_backpack', ['backpackapiurl' => $url]); 1607 if ($bp) { 1608 // Remove connections for users to this backpack. 1609 $sql = "SELECT DISTINCT bb.id 1610 FROM {badge_backpack} bb 1611 LEFT JOIN {badge_external} be ON be. backpackid = bb.externalbackpackid 1612 WHERE bb.externalbackpackid = :backpackid"; 1613 $params = ['backpackid' => $bp->id]; 1614 $externalbackpacks = $DB->get_fieldset_sql($sql, $params); 1615 if ($externalbackpacks) { 1616 list($sql, $params) = $DB->get_in_or_equal($externalbackpacks); 1617 1618 // Delete user external collections references to this backpack. 1619 $DB->execute("DELETE FROM {badge_external} WHERE backpackid " . $sql, $params); 1620 } 1621 $DB->delete_records('badge_backpack', ['externalbackpackid' => $bp->id]); 1622 1623 // Delete deprecated backpack entry. 1624 $DB->delete_records('badge_external_backpack', ['backpackapiurl' => $url]); 1625 } 1626 1627 // Set active external backpack to Badgr.io. 1628 $url = 'https://api.badgr.io/v2'; 1629 if ($bp = $DB->get_record('badge_external_backpack', ['backpackapiurl' => $url])) { 1630 set_config('badges_site_backpack', $bp->id); 1631 } else { 1632 unset_config('badges_site_backpack'); 1633 } 1634 1635 upgrade_main_savepoint(true, 2020040700.00); 1636 } 1637 1638 if ($oldversion < 2020041500.00) { 1639 // Define table to store contentbank contents. 1640 $table = new xmldb_table('contentbank_content'); 1641 1642 // Adding fields to table content_bank. 1643 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1644 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 1645 $table->add_field('contenttype', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 1646 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1647 $table->add_field('instanceid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 1648 $table->add_field('configdata', XMLDB_TYPE_TEXT, null, null, null, null, null); 1649 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1650 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 1651 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1652 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, '0'); 1653 1654 // Adding keys to table contentbank_content. 1655 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 1656 $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']); 1657 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']); 1658 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']); 1659 1660 // Adding indexes to table contentbank_content. 1661 $table->add_index('name', XMLDB_INDEX_NOTUNIQUE, ['name']); 1662 $table->add_index('instance', XMLDB_INDEX_NOTUNIQUE, ['contextid', 'contenttype', 'instanceid']); 1663 1664 if (!$dbman->table_exists($table)) { 1665 $dbman->create_table($table); 1666 } 1667 1668 // Main savepoint reached. 1669 upgrade_main_savepoint(true, 2020041500.00); 1670 } 1671 1672 if ($oldversion < 2020041700.01) { 1673 // Upgrade h5p MIME type for existing h5p files. 1674 $select = $DB->sql_like('filename', '?', false); 1675 $DB->set_field_select( 1676 'files', 1677 'mimetype', 1678 'application/zip.h5p', 1679 $select, 1680 array('%.h5p') 1681 ); 1682 1683 upgrade_main_savepoint(true, 2020041700.01); 1684 } 1685 1686 if ($oldversion < 2020042800.01) { 1687 // Delete obsolete config value. 1688 unset_config('enablesafebrowserintegration'); 1689 // Clean up config of the old plugin. 1690 unset_all_config_for_plugin('quizaccess_safebrowser'); 1691 1692 upgrade_main_savepoint(true, 2020042800.01); 1693 } 1694 1695 if ($oldversion < 2020051900.01) { 1696 // Define field component to be added to event. 1697 $table = new xmldb_table('event'); 1698 $field = new xmldb_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null, 'repeatid'); 1699 1700 // Conditionally launch add field component. 1701 if (!$dbman->field_exists($table, $field)) { 1702 $dbman->add_field($table, $field); 1703 } 1704 1705 // Define index component (not unique) to be added to event. 1706 $table = new xmldb_table('event'); 1707 $index = new xmldb_index('component', XMLDB_INDEX_NOTUNIQUE, ['component', 'eventtype', 'instance']); 1708 1709 // Conditionally launch add index component. 1710 if (!$dbman->index_exists($table, $index)) { 1711 $dbman->add_index($table, $index); 1712 } 1713 1714 // Main savepoint reached. 1715 upgrade_main_savepoint(true, 2020051900.01); 1716 } 1717 1718 if ($oldversion < 2020052000.00) { 1719 // Define table badge_backpack_oauth2 to be created. 1720 $table = new xmldb_table('badge_backpack_oauth2'); 1721 1722 // Adding fields to table badge_backpack_oauth2. 1723 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 1724 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1725 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1726 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 1727 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1728 $table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1729 $table->add_field('externalbackpackid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 1730 $table->add_field('token', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); 1731 $table->add_field('refreshtoken', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); 1732 $table->add_field('expires', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 1733 $table->add_field('scope', XMLDB_TYPE_TEXT, null, null, null, null, null); 1734 1735 // Adding keys to table badge_backpack_oauth2. 1736 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 1737 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']); 1738 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); 1739 $table->add_key('issuerid', XMLDB_KEY_FOREIGN, ['issuerid'], 'oauth2_issuer', ['id']); 1740 $table->add_key('externalbackpackid', XMLDB_KEY_FOREIGN, ['externalbackpackid'], 'badge_external_backpack', ['id']); 1741 // Conditionally launch create table for badge_backpack_oauth2. 1742 if (!$dbman->table_exists($table)) { 1743 $dbman->create_table($table); 1744 } 1745 1746 // Define field oauth2_issuerid to be added to badge_external_backpack. 1747 $tablebadgeexternalbackpack = new xmldb_table('badge_external_backpack'); 1748 $fieldoauth2issuerid = new xmldb_field('oauth2_issuerid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'password'); 1749 $keybackpackoauth2key = new xmldb_key('backpackoauth2key', XMLDB_KEY_FOREIGN, ['oauth2_issuerid'], 'oauth2_issuer', ['id']); 1750 1751 // Conditionally launch add field oauth2_issuerid. 1752 if (!$dbman->field_exists($tablebadgeexternalbackpack, $fieldoauth2issuerid)) { 1753 $dbman->add_field($tablebadgeexternalbackpack, $fieldoauth2issuerid); 1754 1755 // Launch add key backpackoauth2key. 1756 $dbman->add_key($tablebadgeexternalbackpack, $keybackpackoauth2key); 1757 } 1758 1759 // Define field assertion to be added to badge_external. 1760 $tablebadgeexternal = new xmldb_table('badge_external'); 1761 $fieldassertion = new xmldb_field('assertion', XMLDB_TYPE_TEXT, null, null, null, null, null, 'entityid'); 1762 1763 // Conditionally launch add field assertion. 1764 if (!$dbman->field_exists($tablebadgeexternal, $fieldassertion)) { 1765 $dbman->add_field($tablebadgeexternal, $fieldassertion); 1766 } 1767 1768 // Main savepoint reached. 1769 upgrade_main_savepoint(true, 2020052000.00); 1770 } 1771 1772 if ($oldversion < 2020052200.01) { 1773 1774 // Define field custom to be added to license. 1775 $table = new xmldb_table('license'); 1776 $field = new xmldb_field('custom', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 1777 1778 // Conditionally launch add field custom. 1779 if (!$dbman->field_exists($table, $field)) { 1780 $dbman->add_field($table, $field); 1781 } 1782 1783 // Define field sortorder to be added to license. 1784 $field = new xmldb_field('sortorder', XMLDB_TYPE_INTEGER, '5', null, XMLDB_NOTNULL, null, '0'); 1785 1786 // Conditionally launch add field sortorder. 1787 if (!$dbman->field_exists($table, $field)) { 1788 $dbman->add_field($table, $field); 1789 } 1790 1791 // Define index license (not unique) to be added to files. 1792 $table = new xmldb_table('files'); 1793 $index = new xmldb_index('license', XMLDB_INDEX_NOTUNIQUE, ['license']); 1794 1795 // Conditionally launch add index license. 1796 if (!$dbman->index_exists($table, $index)) { 1797 $dbman->add_index($table, $index); 1798 } 1799 1800 // Upgrade the core license details. 1801 upgrade_core_licenses(); 1802 1803 // Main savepoint reached. 1804 upgrade_main_savepoint(true, 2020052200.01); 1805 } 1806 1807 if ($oldversion < 2020060500.01) { 1808 // Define field moodlenetprofile to be added to user. 1809 $table = new xmldb_table('user'); 1810 $field = new xmldb_field('moodlenetprofile', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'alternatename'); 1811 1812 // Conditionally launch add field moodlenetprofile. 1813 if (!$dbman->field_exists($table, $field)) { 1814 $dbman->add_field($table, $field); 1815 } 1816 1817 // Main savepoint reached. 1818 upgrade_main_savepoint(true, 2020060500.01); 1819 } 1820 1821 // Automatically generated Moodle v3.9.0 release upgrade line. 1822 // Put any upgrade step following this. 1823 if ($oldversion < 2020061500.02) { 1824 // Update default digital age consent map according to the current legislation on each country. 1825 1826 // The default age of digital consent map for 38 and below. 1827 $oldageofdigitalconsentmap = implode(PHP_EOL, [ 1828 '*, 16', 1829 'AT, 14', 1830 'ES, 14', 1831 'US, 13' 1832 ]); 1833 1834 // Check if the current age of digital consent map matches the old one. 1835 if (get_config('moodle', 'agedigitalconsentmap') === $oldageofdigitalconsentmap) { 1836 // If the site is still using the old defaults, upgrade to the new default. 1837 $ageofdigitalconsentmap = implode(PHP_EOL, [ 1838 '*, 16', 1839 'AT, 14', 1840 'BE, 13', 1841 'BG, 14', 1842 'CY, 14', 1843 'CZ, 15', 1844 'DK, 13', 1845 'EE, 13', 1846 'ES, 14', 1847 'FI, 13', 1848 'FR, 15', 1849 'GB, 13', 1850 'GR, 15', 1851 'IT, 14', 1852 'LT, 14', 1853 'LV, 13', 1854 'MT, 13', 1855 'NO, 13', 1856 'PT, 13', 1857 'SE, 13', 1858 'US, 13' 1859 ]); 1860 set_config('agedigitalconsentmap', $ageofdigitalconsentmap); 1861 } 1862 1863 upgrade_main_savepoint(true, 2020061500.02); 1864 } 1865 1866 if ($oldversion < 2020062600.01) { 1867 // Add index to the token field in the external_tokens table. 1868 $table = new xmldb_table('external_tokens'); 1869 $index = new xmldb_index('token', XMLDB_INDEX_NOTUNIQUE, ['token']); 1870 1871 if (!$dbman->index_exists($table, $index)) { 1872 $dbman->add_index($table, $index); 1873 } 1874 1875 upgrade_main_savepoint(true, 2020062600.01); 1876 } 1877 1878 if ($oldversion < 2020071100.01) { 1879 // Clean up completion criteria records referring to NULL course prerequisites. 1880 $select = 'criteriatype = :type AND courseinstance IS NULL'; 1881 $params = ['type' => 8]; // COMPLETION_CRITERIA_TYPE_COURSE. 1882 1883 $DB->delete_records_select('course_completion_criteria', $select, $params); 1884 1885 // Main savepoint reached. 1886 upgrade_main_savepoint(true, 2020071100.01); 1887 } 1888 1889 if ($oldversion < 2020072300.01) { 1890 // Restore and set the guest user if it has been previously removed via GDPR, or set to an nonexistent 1891 // user account. 1892 $currentguestuser = $DB->get_record('user', array('id' => $CFG->siteguest)); 1893 1894 if (!$currentguestuser) { 1895 if (!$guest = $DB->get_record('user', array('username' => 'guest', 'mnethostid' => $CFG->mnet_localhost_id))) { 1896 // Create a guest user account. 1897 $guest = new stdClass(); 1898 $guest->auth = 'manual'; 1899 $guest->username = 'guest'; 1900 $guest->password = hash_internal_user_password('guest'); 1901 $guest->firstname = get_string('guestuser'); 1902 $guest->lastname = ' '; 1903 $guest->email = 'root@localhost'; 1904 $guest->description = get_string('guestuserinfo'); 1905 $guest->mnethostid = $CFG->mnet_localhost_id; 1906 $guest->confirmed = 1; 1907 $guest->lang = $CFG->lang; 1908 $guest->timemodified= time(); 1909 $guest->id = $DB->insert_record('user', $guest); 1910 } 1911 // Set the guest user. 1912 set_config('siteguest', $guest->id); 1913 } 1914 1915 // Main savepoint reached. 1916 upgrade_main_savepoint(true, 2020072300.01); 1917 } 1918 1919 if ($oldversion < 2021052500.01) { 1920 // Delete all user evidence files from users that have been deleted. 1921 $sql = "SELECT DISTINCT f.* 1922 FROM {files} f 1923 LEFT JOIN {context} c ON f.contextid = c.id 1924 WHERE f.component = :component 1925 AND f.filearea = :filearea 1926 AND c.id IS NULL"; 1927 $stalefiles = $DB->get_records_sql($sql, ['component' => 'core_competency', 'filearea' => 'userevidence']); 1928 1929 $fs = get_file_storage(); 1930 foreach ($stalefiles as $stalefile) { 1931 $fs->get_file_instance($stalefile)->delete(); 1932 } 1933 1934 upgrade_main_savepoint(true, 2021052500.01); 1935 } 1936 1937 if ($oldversion < 2021052500.02) { 1938 1939 // Define field timecreated to be added to task_adhoc. 1940 $table = new xmldb_table('task_adhoc'); 1941 $field = new xmldb_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'blocking'); 1942 1943 // Conditionally launch add field timecreated. 1944 if (!$dbman->field_exists($table, $field)) { 1945 $dbman->add_field($table, $field); 1946 } 1947 1948 // Main savepoint reached. 1949 upgrade_main_savepoint(true, 2021052500.02); 1950 } 1951 1952 if ($oldversion < 2021052500.04) { 1953 // Define field metadatasettings to be added to h5p_libraries. 1954 $table = new xmldb_table('h5p_libraries'); 1955 $field = new xmldb_field('metadatasettings', XMLDB_TYPE_TEXT, null, null, null, null, null, 'coreminor'); 1956 1957 // Conditionally launch add field metadatasettings. 1958 if (!$dbman->field_exists($table, $field)) { 1959 $dbman->add_field($table, $field); 1960 } 1961 1962 // Get installed library files that have no metadata settings value. 1963 $params = [ 1964 'component' => 'core_h5p', 1965 'filearea' => 'libraries', 1966 'filename' => 'library.json', 1967 ]; 1968 $sql = "SELECT l.id, f.id as fileid 1969 FROM {files} f 1970 LEFT JOIN {h5p_libraries} l ON f.itemid = l.id 1971 WHERE f.component = :component 1972 AND f.filearea = :filearea 1973 AND f.filename = :filename"; 1974 $libraries = $DB->get_records_sql($sql, $params); 1975 1976 // Update metadatasettings field when the attribute is present in the library.json file. 1977 $fs = get_file_storage(); 1978 foreach ($libraries as $library) { 1979 $jsonfile = $fs->get_file_by_id($library->fileid); 1980 $jsoncontent = json_decode($jsonfile->get_content()); 1981 if (isset($jsoncontent->metadataSettings)) { 1982 unset($library->fileid); 1983 $library->metadatasettings = json_encode($jsoncontent->metadataSettings); 1984 $DB->update_record('h5p_libraries', $library); 1985 } 1986 } 1987 1988 // Main savepoint reached. 1989 upgrade_main_savepoint(true, 2021052500.04); 1990 } 1991 1992 if ($oldversion < 2021052500.05) { 1993 // Define fields to be added to task_scheduled. 1994 $table = new xmldb_table('task_scheduled'); 1995 $field = new xmldb_field('timestarted', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'disabled'); 1996 if (!$dbman->field_exists($table, $field)) { 1997 $dbman->add_field($table, $field); 1998 } 1999 $field = new xmldb_field('hostname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'timestarted'); 2000 if (!$dbman->field_exists($table, $field)) { 2001 $dbman->add_field($table, $field); 2002 } 2003 $field = new xmldb_field('pid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'hostname'); 2004 if (!$dbman->field_exists($table, $field)) { 2005 $dbman->add_field($table, $field); 2006 } 2007 2008 // Define fields to be added to task_adhoc. 2009 $table = new xmldb_table('task_adhoc'); 2010 $field = new xmldb_field('timestarted', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'blocking'); 2011 if (!$dbman->field_exists($table, $field)) { 2012 $dbman->add_field($table, $field); 2013 } 2014 $field = new xmldb_field('hostname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'timestarted'); 2015 if (!$dbman->field_exists($table, $field)) { 2016 $dbman->add_field($table, $field); 2017 } 2018 $field = new xmldb_field('pid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'hostname'); 2019 if (!$dbman->field_exists($table, $field)) { 2020 $dbman->add_field($table, $field); 2021 } 2022 2023 // Define fields to be added to task_log. 2024 $table = new xmldb_table('task_log'); 2025 $field = new xmldb_field('hostname', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'output'); 2026 if (!$dbman->field_exists($table, $field)) { 2027 $dbman->add_field($table, $field); 2028 } 2029 $field = new xmldb_field('pid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'hostname'); 2030 if (!$dbman->field_exists($table, $field)) { 2031 $dbman->add_field($table, $field); 2032 } 2033 2034 // Main savepoint reached. 2035 upgrade_main_savepoint(true, 2021052500.05); 2036 } 2037 2038 if ($oldversion < 2021052500.06) { 2039 // Define table to store virus infected details. 2040 $table = new xmldb_table('infected_files'); 2041 2042 // Adding fields to table infected_files. 2043 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2044 $table->add_field('filename', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); 2045 $table->add_field('quarantinedfile', XMLDB_TYPE_TEXT, null, null, null, null, null); 2046 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2047 $table->add_field('reason', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); 2048 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2049 2050 // Adding keys to table infected_files. 2051 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 2052 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); 2053 2054 // Conditionally launch create table for infected_files. 2055 if (!$dbman->table_exists($table)) { 2056 $dbman->create_table($table); 2057 } 2058 upgrade_main_savepoint(true, 2021052500.06); 2059 } 2060 2061 if ($oldversion < 2021052500.13) { 2062 // Remove all the files with component='core_h5p' and filearea='editor' because they won't be used anymore. 2063 $fs = get_file_storage(); 2064 $syscontext = context_system::instance(); 2065 $fs->delete_area_files($syscontext->id, 'core_h5p', 'editor'); 2066 2067 // Main savepoint reached. 2068 upgrade_main_savepoint(true, 2021052500.13); 2069 } 2070 2071 if ($oldversion < 2021052500.15) { 2072 // Copy From id captures the id of the source course when a new course originates from a restore 2073 // of another course on the same site. 2074 $table = new xmldb_table('course'); 2075 $field = new xmldb_field('originalcourseid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 2076 2077 if (!$dbman->field_exists($table, $field)) { 2078 $dbman->add_field($table, $field); 2079 } 2080 2081 // Main savepoint reached. 2082 upgrade_main_savepoint(true, 2021052500.15); 2083 } 2084 2085 if ($oldversion < 2021052500.19) { 2086 // Define table oauth2_refresh_token to be created. 2087 $table = new xmldb_table('oauth2_refresh_token'); 2088 2089 // Adding fields to table oauth2_refresh_token. 2090 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2091 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2092 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2093 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2094 $table->add_field('issuerid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2095 $table->add_field('token', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); 2096 $table->add_field('scopehash', XMLDB_TYPE_CHAR, 40, null, XMLDB_NOTNULL, null, null); 2097 2098 // Adding keys to table oauth2_refresh_token. 2099 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 2100 $table->add_key('issueridkey', XMLDB_KEY_FOREIGN, ['issuerid'], 'oauth2_issuer', ['id']); 2101 $table->add_key('useridkey', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); 2102 2103 // Adding indexes to table oauth2_refresh_token. 2104 $table->add_index('userid-issuerid-scopehash', XMLDB_INDEX_UNIQUE, array('userid', 'issuerid', 'scopehash')); 2105 2106 // Conditionally launch create table for oauth2_refresh_token. 2107 if (!$dbman->table_exists($table)) { 2108 $dbman->create_table($table); 2109 } 2110 2111 // Main savepoint reached. 2112 upgrade_main_savepoint(true, 2021052500.19); 2113 } 2114 2115 if ($oldversion < 2021052500.20) { 2116 2117 // Define index modulename-instance-eventtype (not unique) to be added to event. 2118 $table = new xmldb_table('event'); 2119 $index = new xmldb_index('modulename-instance-eventtype', XMLDB_INDEX_NOTUNIQUE, ['modulename', 'instance', 'eventtype']); 2120 2121 // Conditionally launch add index modulename-instance-eventtype. 2122 if (!$dbman->index_exists($table, $index)) { 2123 $dbman->add_index($table, $index); 2124 } 2125 2126 // Define index modulename-instance (not unique) to be dropped form event. 2127 $table = new xmldb_table('event'); 2128 $index = new xmldb_index('modulename-instance', XMLDB_INDEX_NOTUNIQUE, ['modulename', 'instance']); 2129 2130 // Conditionally launch drop index modulename-instance. 2131 if ($dbman->index_exists($table, $index)) { 2132 $dbman->drop_index($table, $index); 2133 } 2134 2135 // Main savepoint reached. 2136 upgrade_main_savepoint(true, 2021052500.20); 2137 } 2138 2139 if ($oldversion < 2021052500.24) { 2140 // Define fields tutorial and example to be added to h5p_libraries. 2141 $table = new xmldb_table('h5p_libraries'); 2142 2143 // Add tutorial field. 2144 $field = new xmldb_field('tutorial', XMLDB_TYPE_TEXT, null, null, null, null, null, 'metadatasettings'); 2145 if (!$dbman->field_exists($table, $field)) { 2146 $dbman->add_field($table, $field); 2147 } 2148 2149 // Add example field. 2150 $field = new xmldb_field('example', XMLDB_TYPE_TEXT, null, null, null, null, null, 'tutorial'); 2151 2152 if (!$dbman->field_exists($table, $field)) { 2153 $dbman->add_field($table, $field); 2154 } 2155 2156 // Main savepoint reached. 2157 upgrade_main_savepoint(true, 2021052500.24); 2158 } 2159 2160 if ($oldversion < 2021052500.26) { 2161 // Delete orphaned course_modules_completion rows; these were not deleted properly 2162 // by remove_course_contents function. 2163 $DB->delete_records_select('course_modules_completion', " 2164 NOT EXISTS ( 2165 SELECT 1 2166 FROM {course_modules} cm 2167 WHERE cm.id = {course_modules_completion}.coursemoduleid 2168 )"); 2169 upgrade_main_savepoint(true, 2021052500.26); 2170 } 2171 2172 if ($oldversion < 2021052500.27) { 2173 // Script to fix incorrect records of "hidden" field in existing grade items. 2174 $sql = "SELECT cm.instance, cm.course 2175 FROM {course_modules} cm 2176 JOIN {modules} m ON m.id = cm.module 2177 WHERE m.name = :module AND cm.visible = :visible"; 2178 $hidequizlist = $DB->get_recordset_sql($sql, ['module' => 'quiz', 'visible' => 0]); 2179 2180 foreach ($hidequizlist as $hidequiz) { 2181 $params = [ 2182 'itemmodule' => 'quiz', 2183 'courseid' => $hidequiz->course, 2184 'iteminstance' => $hidequiz->instance, 2185 ]; 2186 2187 $DB->set_field('grade_items', 'hidden', 1, $params); 2188 } 2189 $hidequizlist->close(); 2190 2191 upgrade_main_savepoint(true, 2021052500.27); 2192 } 2193 2194 if ($oldversion < 2021052500.29) { 2195 // Get the current guest user which is also set as 'deleted'. 2196 $guestuser = $DB->get_record('user', ['id' => $CFG->siteguest, 'deleted' => 1]); 2197 // If there is a deleted guest user, reset the user to not be deleted and make sure the related 2198 // user context exists. 2199 if ($guestuser) { 2200 $guestuser->deleted = 0; 2201 $DB->update_record('user', $guestuser); 2202 2203 // Get the guest user context. 2204 $guestusercontext = $DB->get_record('context', 2205 ['contextlevel' => CONTEXT_USER, 'instanceid' => $guestuser->id]); 2206 2207 // If the guest user context does not exist, create it. 2208 if (!$guestusercontext) { 2209 $record = new stdClass(); 2210 $record->contextlevel = CONTEXT_USER; 2211 $record->instanceid = $guestuser->id; 2212 $record->depth = 0; 2213 // The path is not known before insert. 2214 $record->path = null; 2215 $record->locked = 0; 2216 2217 $record->id = $DB->insert_record('context', $record); 2218 2219 // Update the path. 2220 $record->path = '/' . SYSCONTEXTID . '/' . $record->id; 2221 $record->depth = substr_count($record->path, '/'); 2222 $DB->update_record('context', $record); 2223 } 2224 } 2225 2226 // Main savepoint reached. 2227 upgrade_main_savepoint(true, 2021052500.29); 2228 } 2229 2230 if ($oldversion < 2021052500.30) { 2231 // Reset analytics model output dir if it's the default value. 2232 $modeloutputdir = get_config('analytics', 'modeloutputdir'); 2233 if (strcasecmp($modeloutputdir, $CFG->dataroot . DIRECTORY_SEPARATOR . 'models') == 0) { 2234 set_config('modeloutputdir', '', 'analytics'); 2235 } 2236 2237 // Main savepoint reached. 2238 upgrade_main_savepoint(true, 2021052500.30); 2239 } 2240 2241 if ($oldversion < 2021052500.32) { 2242 // Define field downloadcontent to be added to course. 2243 $table = new xmldb_table('course'); 2244 $field = new xmldb_field('downloadcontent', XMLDB_TYPE_INTEGER, '1', null, null, null, null, 'visibleold'); 2245 2246 if (!$dbman->field_exists($table, $field)) { 2247 $dbman->add_field($table, $field); 2248 } 2249 2250 // Main savepoint reached. 2251 upgrade_main_savepoint(true, 2021052500.32); 2252 } 2253 2254 if ($oldversion < 2021052500.33) { 2255 $table = new xmldb_table('badge_backpack'); 2256 2257 // There is no key_exists, so test the equivalent index. 2258 $oldindex = new xmldb_index('backpackcredentials', XMLDB_KEY_UNIQUE, ['userid', 'externalbackpackid']); 2259 if (!$dbman->index_exists($table, $oldindex)) { 2260 // All external backpack providers/hosts are now exclusively stored in badge_external_backpack. 2261 // All credentials are stored in badge_backpack and are unique per user, backpack. 2262 $uniquekey = new xmldb_key('backpackcredentials', XMLDB_KEY_UNIQUE, ['userid', 'externalbackpackid']); 2263 $dbman->add_key($table, $uniquekey); 2264 } 2265 2266 // Drop the password field as this is moved to badge_backpack. 2267 $table = new xmldb_table('badge_external_backpack'); 2268 $field = new xmldb_field('password', XMLDB_TYPE_CHAR, '50'); 2269 if ($dbman->field_exists($table, $field)) { 2270 // If there is a current backpack set then copy it across to the new structure. 2271 if ($CFG->badges_defaultissuercontact) { 2272 // Get the currently used site backpacks. 2273 $records = $DB->get_records_select('badge_external_backpack', "password IS NOT NULL AND password != ''"); 2274 $backpack = [ 2275 'userid' => '0', 2276 'email' => $CFG->badges_defaultissuercontact, 2277 'backpackuid' => -1 2278 ]; 2279 2280 // Create records corresponding to the site backpacks. 2281 foreach ($records as $record) { 2282 $backpack['password'] = $record->password; 2283 $backpack['externalbackpackid'] = $record->id; 2284 $DB->insert_record('badge_backpack', (object) $backpack); 2285 } 2286 } 2287 2288 $dbman->drop_field($table, $field); 2289 } 2290 2291 // Main savepoint reached. 2292 upgrade_main_savepoint(true, 2021052500.33); 2293 } 2294 2295 if ($oldversion < 2021052500.36) { 2296 // Define table payment_accounts to be created. 2297 $table = new xmldb_table('payment_accounts'); 2298 2299 // Adding fields to table payment_accounts. 2300 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2301 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 2302 $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null); 2303 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2304 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 2305 $table->add_field('archived', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 2306 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 2307 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 2308 2309 // Adding keys to table payment_accounts. 2310 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 2311 2312 // Conditionally launch create table for payment_accounts. 2313 if (!$dbman->table_exists($table)) { 2314 $dbman->create_table($table); 2315 } 2316 2317 // Define table payment_gateways to be created. 2318 $table = new xmldb_table('payment_gateways'); 2319 2320 // Adding fields to table payment_gateways. 2321 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2322 $table->add_field('accountid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2323 $table->add_field('gateway', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 2324 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1'); 2325 $table->add_field('config', XMLDB_TYPE_TEXT, null, null, null, null, null); 2326 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2327 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2328 2329 // Adding keys to table payment_gateways. 2330 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 2331 $table->add_key('accountid', XMLDB_KEY_FOREIGN, ['accountid'], 'payment_accounts', ['id']); 2332 2333 // Conditionally launch create table for payment_gateways. 2334 if (!$dbman->table_exists($table)) { 2335 $dbman->create_table($table); 2336 } 2337 2338 // Define table payments to be created. 2339 $table = new xmldb_table('payments'); 2340 2341 // Adding fields to table payments. 2342 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2343 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 2344 $table->add_field('paymentarea', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL, null, null); 2345 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2346 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2347 $table->add_field('amount', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null); 2348 $table->add_field('currency', XMLDB_TYPE_CHAR, '3', null, XMLDB_NOTNULL, null, null); 2349 $table->add_field('accountid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2350 $table->add_field('gateway', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 2351 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2352 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2353 2354 // Adding keys to table payments. 2355 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 2356 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); 2357 $table->add_key('accountid', XMLDB_KEY_FOREIGN, ['accountid'], 'payment_accounts', ['id']); 2358 2359 // Adding indexes to table payments. 2360 $table->add_index('gateway', XMLDB_INDEX_NOTUNIQUE, ['gateway']); 2361 $table->add_index('component-paymentarea-itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'paymentarea', 'itemid']); 2362 2363 // Conditionally launch create table for payments. 2364 if (!$dbman->table_exists($table)) { 2365 $dbman->create_table($table); 2366 } 2367 2368 // Main savepoint reached. 2369 upgrade_main_savepoint(true, 2021052500.36); 2370 } 2371 2372 if ($oldversion < 2021052500.42) { 2373 // Get all lessons that are set with a completion criteria of 'requires grade' but with no grade type set. 2374 $sql = "SELECT cm.id 2375 FROM {course_modules} cm 2376 JOIN {lesson} l ON l.id = cm.instance 2377 JOIN {modules} m ON m.id = cm.module 2378 WHERE m.name = :name AND cm.completiongradeitemnumber IS NOT NULL AND l.grade = :grade"; 2379 2380 do { 2381 if ($invalidconfigrations = $DB->get_records_sql($sql, ['name' => 'lesson', 'grade' => 0], 0, 1000)) { 2382 list($insql, $inparams) = $DB->get_in_or_equal(array_keys($invalidconfigrations), SQL_PARAMS_NAMED); 2383 $DB->set_field_select('course_modules', 'completiongradeitemnumber', null, "id $insql", $inparams); 2384 } 2385 } while ($invalidconfigrations); 2386 2387 upgrade_main_savepoint(true, 2021052500.42); 2388 } 2389 2390 if ($oldversion < 2021052500.55) { 2391 $DB->delete_records_select('event', "eventtype = 'category' AND categoryid = 0 AND userid <> 0"); 2392 2393 upgrade_main_savepoint(true, 2021052500.55); 2394 } 2395 2396 if ($oldversion < 2021052500.59) { 2397 // Define field visibility to be added to contentbank_content. 2398 $table = new xmldb_table('contentbank_content'); 2399 $field = new xmldb_field('visibility', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'contextid'); 2400 2401 // Conditionally launch add field visibility. 2402 if (!$dbman->field_exists($table, $field)) { 2403 $dbman->add_field($table, $field); 2404 } 2405 2406 // Main savepoint reached. 2407 upgrade_main_savepoint(true, 2021052500.59); 2408 } 2409 2410 if ($oldversion < 2021052500.60) { 2411 2412 // We are going to remove the field 'hidepicture' from the groups 2413 // so we need to remove the pictures from those groups. But we prevent 2414 // the execution twice because this could be executed again when upgrading 2415 // to different versions. 2416 if ($dbman->field_exists('groups', 'hidepicture')) { 2417 2418 $sql = "SELECT g.id, g.courseid, ctx.id AS contextid 2419 FROM {groups} g 2420 JOIN {context} ctx 2421 ON ctx.instanceid = g.courseid 2422 AND ctx.contextlevel = :contextlevel 2423 WHERE g.hidepicture = 1"; 2424 2425 // Selecting all the groups that have hide picture enabled, and organising them by context. 2426 $groupctx = []; 2427 $records = $DB->get_recordset_sql($sql, ['contextlevel' => CONTEXT_COURSE]); 2428 foreach ($records as $record) { 2429 if (!isset($groupctx[$record->contextid])) { 2430 $groupctx[$record->contextid] = []; 2431 } 2432 $groupctx[$record->contextid][] = $record->id; 2433 } 2434 $records->close(); 2435 2436 // Deleting the group files. 2437 $fs = get_file_storage(); 2438 foreach ($groupctx as $contextid => $groupids) { 2439 list($in, $inparams) = $DB->get_in_or_equal($groupids, SQL_PARAMS_NAMED); 2440 $fs->delete_area_files_select($contextid, 'group', 'icon', $in, $inparams); 2441 } 2442 2443 // Updating the database to remove picture from all those groups. 2444 $sql = "UPDATE {groups} SET picture = :pic WHERE hidepicture = :hide"; 2445 $DB->execute($sql, ['pic' => 0, 'hide' => 1]); 2446 } 2447 2448 // Define field hidepicture to be dropped from groups. 2449 $table = new xmldb_table('groups'); 2450 $field = new xmldb_field('hidepicture'); 2451 2452 // Conditionally launch drop field hidepicture. 2453 if ($dbman->field_exists($table, $field)) { 2454 $dbman->drop_field($table, $field); 2455 } 2456 2457 // Main savepoint reached. 2458 upgrade_main_savepoint(true, 2021052500.60); 2459 } 2460 2461 if ($oldversion < 2021052500.64) { 2462 // Get all the external backpacks and update the sortorder column, to avoid repeated/wrong values. As sortorder was not 2463 // used since now, the id column will be the criteria to follow for re-ordering them with a valid value. 2464 $i = 1; 2465 $records = $DB->get_records('badge_external_backpack', null, 'id ASC'); 2466 foreach ($records as $record) { 2467 $record->sortorder = $i++; 2468 $DB->update_record('badge_external_backpack', $record); 2469 } 2470 2471 upgrade_main_savepoint(true, 2021052500.64); 2472 } 2473 2474 if ($oldversion < 2021052500.67) { 2475 // The $CFG->badges_site_backpack setting has been removed because it's not required anymore. From now, the default backpack 2476 // will be the one with lower sortorder value. 2477 unset_config('badges_site_backpack'); 2478 2479 upgrade_main_savepoint(true, 2021052500.67); 2480 } 2481 2482 if ($oldversion < 2021052500.69) { 2483 2484 // Define field type to be added to oauth2_issuer. 2485 $table = new xmldb_table('oauth2_issuer'); 2486 $field = new xmldb_field('servicetype', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'requireconfirmation'); 2487 2488 // Conditionally launch add field type. 2489 if (!$dbman->field_exists($table, $field)) { 2490 $dbman->add_field($table, $field); 2491 } 2492 2493 // Set existing values to the proper servicetype value. 2494 // It's not critical if the servicetype column doesn't contain the proper value for Google, Microsoft, Facebook or 2495 // Nextcloud services because, for now, this value is used for services using different discovery method. 2496 // However, let's try to upgrade it using the default value for the baseurl or image. If any of these default values 2497 // have been changed, the servicetype column will remain NULL. 2498 $recordset = $DB->get_recordset('oauth2_issuer'); 2499 foreach ($recordset as $record) { 2500 if ($record->baseurl == 'https://accounts.google.com/') { 2501 $record->servicetype = 'google'; 2502 $DB->update_record('oauth2_issuer', $record); 2503 } else if ($record->image == 'https://www.microsoft.com/favicon.ico') { 2504 $record->servicetype = 'microsoft'; 2505 $DB->update_record('oauth2_issuer', $record); 2506 } else if ($record->image == 'https://facebookbrand.com/wp-content/uploads/2016/05/flogo_rgb_hex-brc-site-250.png') { 2507 $record->servicetype = 'facebook'; 2508 $DB->update_record('oauth2_issuer', $record); 2509 } else if ($record->image == 'https://nextcloud.com/wp-content/themes/next/assets/img/common/favicon.png?x16328') { 2510 $record->servicetype = 'nextcloud'; 2511 $DB->update_record('oauth2_issuer', $record); 2512 } 2513 } 2514 $recordset->close(); 2515 2516 // Main savepoint reached. 2517 upgrade_main_savepoint(true, 2021052500.69); 2518 } 2519 2520 if ($oldversion < 2021052500.74) { 2521 // Define field 'showactivitydates' to be added to course table. 2522 $table = new xmldb_table('course'); 2523 $field = new xmldb_field('showactivitydates', XMLDB_TYPE_INTEGER, '1', null, 2524 XMLDB_NOTNULL, null, '0', 'originalcourseid'); 2525 2526 if (!$dbman->field_exists($table, $field)) { 2527 $dbman->add_field($table, $field); 2528 } 2529 2530 // Main savepoint reached. 2531 upgrade_main_savepoint(true, 2021052500.74); 2532 } 2533 2534 if ($oldversion < 2021052500.75) { 2535 // Define field 'showcompletionconditions' to be added to course. 2536 $table = new xmldb_table('course'); 2537 $field = new xmldb_field('showcompletionconditions', XMLDB_TYPE_INTEGER, '1', null, 2538 XMLDB_NOTNULL, null, '1', 'completionnotify'); 2539 2540 if (!$dbman->field_exists($table, $field)) { 2541 $dbman->add_field($table, $field); 2542 } 2543 2544 // Main savepoint reached. 2545 upgrade_main_savepoint(true, 2021052500.75); 2546 } 2547 2548 if ($oldversion < 2021052500.78) { 2549 2550 // Define field enabled to be added to h5p_libraries. 2551 $table = new xmldb_table('h5p_libraries'); 2552 $field = new xmldb_field('enabled', XMLDB_TYPE_INTEGER, '1', null, null, null, '1', 'example'); 2553 2554 // Conditionally launch add field enabled. 2555 if (!$dbman->field_exists($table, $field)) { 2556 $dbman->add_field($table, $field); 2557 } 2558 2559 // Main savepoint reached. 2560 upgrade_main_savepoint(true, 2021052500.78); 2561 } 2562 2563 if ($oldversion < 2021052500.83) { 2564 2565 // Define field loginpagename to be added to oauth2_issuer. 2566 $table = new xmldb_table('oauth2_issuer'); 2567 $field = new xmldb_field('loginpagename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'servicetype'); 2568 2569 // Conditionally launch add field loginpagename. 2570 if (!$dbman->field_exists($table, $field)) { 2571 $dbman->add_field($table, $field); 2572 } 2573 2574 // Main savepoint reached. 2575 upgrade_main_savepoint(true, 2021052500.83); 2576 } 2577 2578 if ($oldversion < 2021052500.84) { 2579 require_once($CFG->dirroot . '/user/profile/field/social/upgradelib.php'); 2580 $table = new xmldb_table('user'); 2581 $tablecolumns = ['icq', 'skype', 'aim', 'yahoo', 'msn', 'url']; 2582 2583 foreach ($tablecolumns as $column) { 2584 $field = new xmldb_field($column); 2585 if ($dbman->field_exists($table, $field)) { 2586 user_profile_social_moveto_profilefield($column); 2587 $dbman->drop_field($table, $field); 2588 } 2589 } 2590 2591 // Update all module availability if it relies on the old user fields. 2592 user_profile_social_update_module_availability(); 2593 2594 // Remove field mapping for oauth2. 2595 $DB->delete_records('oauth2_user_field_mapping', array('internalfield' => 'url')); 2596 2597 // Main savepoint reached. 2598 upgrade_main_savepoint(true, 2021052500.84); 2599 } 2600 2601 if ($oldversion < 2021052500.85) { 2602 require_once($CFG->libdir . '/db/upgradelib.php'); 2603 2604 // Check if this site has executed the problematic upgrade steps. 2605 $needsfixing = upgrade_calendar_site_status(false); 2606 2607 // Only queue the task if this site has been affected by the problematic upgrade step. 2608 if ($needsfixing) { 2609 2610 // Create adhoc task to search and recover orphaned calendar events. 2611 $record = new \stdClass(); 2612 $record->classname = '\core\task\calendar_fix_orphaned_events'; 2613 2614 // Next run time based from nextruntime computation in \core\task\manager::queue_adhoc_task(). 2615 $nextruntime = time() - 1; 2616 $record->nextruntime = $nextruntime; 2617 $DB->insert_record('task_adhoc', $record); 2618 } 2619 2620 // Main savepoint reached. 2621 upgrade_main_savepoint(true, 2021052500.85); 2622 } 2623 2624 if ($oldversion < 2021052500.87) { 2625 // Changing the default of field showcompletionconditions on table course to 0. 2626 $table = new xmldb_table('course'); 2627 $field = new xmldb_field('showcompletionconditions', XMLDB_TYPE_INTEGER, '1', null, null, null, null, 'showactivitydates'); 2628 2629 // Launch change of nullability for field showcompletionconditions. 2630 $dbman->change_field_notnull($table, $field); 2631 2632 // Launch change of default for field showcompletionconditions. 2633 $dbman->change_field_default($table, $field); 2634 2635 // Set showcompletionconditions to null for courses which don't track completion. 2636 $sql = "UPDATE {course} 2637 SET showcompletionconditions = null 2638 WHERE enablecompletion <> 1"; 2639 $DB->execute($sql); 2640 2641 // Main savepoint reached. 2642 upgrade_main_savepoint(true, 2021052500.87); 2643 } 2644 2645 if ($oldversion < 2021052500.90) { 2646 // Remove usemodchooser user preference for every user. 2647 $DB->delete_records('user_preferences', ['name' => 'usemodchooser']); 2648 2649 // Main savepoint reached. 2650 upgrade_main_savepoint(true, 2021052500.90); 2651 } 2652 2653 if ($oldversion < 2021060200.00) { 2654 2655 // Define index name (not unique) to be added to user_preferences. 2656 $table = new xmldb_table('user_preferences'); 2657 $index = new xmldb_index('name', XMLDB_INDEX_NOTUNIQUE, ['name']); 2658 2659 // Conditionally launch add index name. 2660 if (!$dbman->index_exists($table, $index)) { 2661 $dbman->add_index($table, $index); 2662 } 2663 2664 // Main savepoint reached. 2665 upgrade_main_savepoint(true, 2021060200.00); 2666 } 2667 2668 if ($oldversion < 2021060900.00) { 2669 // Update the externalfield to be larger. 2670 $table = new xmldb_table('oauth2_user_field_mapping'); 2671 $field = new xmldb_field('externalfield', XMLDB_TYPE_CHAR, '500', null, XMLDB_NOTNULL, false, null, 'issuerid'); 2672 $dbman->change_field_type($table, $field); 2673 2674 // Main savepoint reached. 2675 upgrade_main_savepoint(true, 2021060900.00); 2676 } 2677 2678 if ($oldversion < 2021072800.01) { 2679 // Define table reportbuilder_report to be created. 2680 $table = new xmldb_table('reportbuilder_report'); 2681 2682 // Adding fields to table reportbuilder_report. 2683 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2684 $table->add_field('source', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 2685 $table->add_field('type', XMLDB_TYPE_INTEGER, '2', null, XMLDB_NOTNULL, null, '0'); 2686 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2687 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 2688 $table->add_field('area', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 2689 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2690 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2691 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2692 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2693 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2694 2695 // Adding keys to table reportbuilder_report. 2696 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 2697 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']); 2698 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']); 2699 $table->add_key('contextid', XMLDB_KEY_FOREIGN, ['contextid'], 'context', ['id']); 2700 2701 // Conditionally launch create table for reportbuilder_report. 2702 if (!$dbman->table_exists($table)) { 2703 $dbman->create_table($table); 2704 } 2705 2706 // Main savepoint reached. 2707 upgrade_main_savepoint(true, 2021072800.01); 2708 } 2709 2710 if ($oldversion < 2021090200.01) { 2711 // Remove qformat_webct (unless it has manually been added back). 2712 if (!file_exists($CFG->dirroot . '/question/format/webct/format.php')) { 2713 unset_all_config_for_plugin('qformat_webct'); 2714 } 2715 2716 // Main savepoint reached. 2717 upgrade_main_savepoint(true, 2021090200.01); 2718 } 2719 2720 if ($oldversion < 2021091100.01) { 2721 // If message_jabber is no longer present, remove it. 2722 if (!file_exists($CFG->dirroot . '/message/output/jabber/message_output_jabber.php')) { 2723 // Remove Jabber from the notification plugins list. 2724 $DB->delete_records('message_processors', ['name' => 'jabber']); 2725 2726 // Remove user preference settings. 2727 $DB->delete_records('user_preferences', ['name' => 'message_processor_jabber_jabberid']); 2728 $sql = 'SELECT * 2729 FROM {user_preferences} up 2730 WHERE ' . $DB->sql_like('up.name', ':name', false, false) . ' AND ' . 2731 $DB->sql_like('up.value', ':value', false, false); 2732 $params = [ 2733 'name' => 'message_provider_%', 2734 'value' => '%jabber%', 2735 ]; 2736 $jabbersettings = $DB->get_recordset_sql($sql, $params); 2737 foreach ($jabbersettings as $jabbersetting) { 2738 // Remove 'jabber' from the value. 2739 $jabbersetting->value = implode(',', array_diff(explode(',', $jabbersetting->value), ['jabber'])); 2740 $DB->update_record('user_preferences', $jabbersetting); 2741 } 2742 $jabbersettings->close(); 2743 2744 // Clean config settings. 2745 unset_config('jabberhost'); 2746 unset_config('jabberserver'); 2747 unset_config('jabberusername'); 2748 unset_config('jabberpassword'); 2749 unset_config('jabberport'); 2750 2751 // Remove default notification preferences. 2752 $like = $DB->sql_like('name', '?', true, true, false, '|'); 2753 $params = [$DB->sql_like_escape('jabber_provider_', '|') . '%']; 2754 $DB->delete_records_select('config_plugins', $like, $params); 2755 2756 // Clean config config settings. 2757 unset_all_config_for_plugin('message_jabber'); 2758 } 2759 2760 upgrade_main_savepoint(true, 2021091100.01); 2761 } 2762 2763 if ($oldversion < 2021091100.02) { 2764 // Set the description field to HTML format for the Default course category. 2765 $category = $DB->get_record('course_categories', ['id' => 1]); 2766 2767 if (!empty($category) && $category->descriptionformat == FORMAT_MOODLE) { 2768 // Format should be changed only if it's still set to FORMAT_MOODLE. 2769 if (!is_null($category->description)) { 2770 // If description is not empty, format the content to HTML. 2771 $category->description = format_text($category->description, FORMAT_MOODLE); 2772 } 2773 $category->descriptionformat = FORMAT_HTML; 2774 $DB->update_record('course_categories', $category); 2775 } 2776 2777 // Main savepoint reached. 2778 upgrade_main_savepoint(true, 2021091100.02); 2779 } 2780 2781 if ($oldversion < 2021091700.01) { 2782 // Default 'off' for existing sites as this is the behaviour they had earlier. 2783 set_config('enroladminnewcourse', false); 2784 2785 // Main savepoint reached. 2786 upgrade_main_savepoint(true, 2021091700.01); 2787 } 2788 2789 if ($oldversion < 2021091700.02) { 2790 // If portfolio_picasa is no longer present, remove it. 2791 if (!file_exists($CFG->dirroot . '/portfolio/picasa/version.php')) { 2792 $instance = $DB->get_record('portfolio_instance', ['plugin' => 'picasa']); 2793 if (!empty($instance)) { 2794 // Remove all records from portfolio_instance_config. 2795 $DB->delete_records('portfolio_instance_config', ['instance' => $instance->id]); 2796 // Remove all records from portfolio_instance_user. 2797 $DB->delete_records('portfolio_instance_user', ['instance' => $instance->id]); 2798 // Remove all records from portfolio_log. 2799 $DB->delete_records('portfolio_log', ['portfolio' => $instance->id]); 2800 // Remove all records from portfolio_tempdata. 2801 $DB->delete_records('portfolio_tempdata', ['instance' => $instance->id]); 2802 // Remove the record from the portfolio_instance table. 2803 $DB->delete_records('portfolio_instance', ['id' => $instance->id]); 2804 } 2805 2806 // Clean config. 2807 unset_all_config_for_plugin('portfolio_picasa'); 2808 } 2809 2810 upgrade_main_savepoint(true, 2021091700.02); 2811 } 2812 2813 if ($oldversion < 2021091700.03) { 2814 // If repository_picasa is no longer present, remove it. 2815 if (!file_exists($CFG->dirroot . '/repository/picasa/version.php')) { 2816 $instance = $DB->get_record('repository', ['type' => 'picasa']); 2817 if (!empty($instance)) { 2818 // Remove all records from repository_instance_config table. 2819 $DB->delete_records('repository_instance_config', ['instanceid' => $instance->id]); 2820 // Remove all records from repository_instances table. 2821 $DB->delete_records('repository_instances', ['typeid' => $instance->id]); 2822 // Remove the record from the repository table. 2823 $DB->delete_records('repository', ['id' => $instance->id]); 2824 } 2825 2826 // Clean config. 2827 unset_all_config_for_plugin('picasa'); 2828 2829 // Remove orphaned files. 2830 upgrade_delete_orphaned_file_records(); 2831 } 2832 2833 upgrade_main_savepoint(true, 2021091700.03); 2834 } 2835 2836 if ($oldversion < 2021091700.04) { 2837 // Remove media_swf (unless it has manually been added back). 2838 if (!file_exists($CFG->dirroot . '/media/player/swf/classes/plugin.php')) { 2839 unset_all_config_for_plugin('media_swf'); 2840 } 2841 2842 upgrade_main_savepoint(true, 2021091700.04); 2843 } 2844 2845 if ($oldversion < 2021092400.01) { 2846 // If tool_health is no longer present, remove it. 2847 if (!file_exists($CFG->dirroot . '/admin/tool/health/version.php')) { 2848 // Clean config. 2849 unset_all_config_for_plugin('tool_health'); 2850 } 2851 2852 // Main savepoint reached. 2853 upgrade_main_savepoint(true, 2021092400.01); 2854 } 2855 2856 if ($oldversion < 2021092400.03) { 2857 // Remove repository_picasa configuration (unless it has manually been added back). 2858 if (!file_exists($CFG->dirroot . '/repository/picasa/version.php')) { 2859 unset_all_config_for_plugin('repository_picasa'); 2860 } 2861 2862 upgrade_main_savepoint(true, 2021092400.03); 2863 } 2864 2865 if ($oldversion < 2021100300.01) { 2866 // Remove repository_skydrive (unless it has manually been added back). 2867 if (!file_exists($CFG->dirroot . '/repository/skydrive/lib.php')) { 2868 unset_all_config_for_plugin('repository_skydrive'); 2869 } 2870 2871 // Main savepoint reached. 2872 upgrade_main_savepoint(true, 2021100300.01); 2873 } 2874 2875 if ($oldversion < 2021100300.02) { 2876 // Remove filter_censor (unless it has manually been added back). 2877 if (!file_exists($CFG->dirroot . '/filter/censor/filter.php')) { 2878 unset_all_config_for_plugin('filter_censor'); 2879 } 2880 2881 // Main savepoint reached. 2882 upgrade_main_savepoint(true, 2021100300.02); 2883 } 2884 2885 if ($oldversion < 2021100600.01) { 2886 // Remove qformat_examview (unless it has manually been added back). 2887 if (!file_exists($CFG->dirroot . '/question/format/examview/format.php')) { 2888 unset_all_config_for_plugin('qformat_examview'); 2889 } 2890 2891 // Main savepoint reached. 2892 upgrade_main_savepoint(true, 2021100600.01); 2893 } 2894 2895 if ($oldversion < 2021100600.02) { 2896 $table = new xmldb_table('course_completion_defaults'); 2897 2898 // Adding fields to table course_completion_defaults. 2899 $field = new xmldb_field('completionpassgrade', XMLDB_TYPE_INTEGER, '1', null, 2900 XMLDB_NOTNULL, null, '0', 'completionusegrade'); 2901 2902 // Conditionally launch add field for course_completion_defaults. 2903 if (!$dbman->field_exists($table, $field)) { 2904 $dbman->add_field($table, $field); 2905 } 2906 2907 upgrade_main_savepoint(true, 2021100600.02); 2908 } 2909 2910 if ($oldversion < 2021100600.03) { 2911 $table = new xmldb_table('course_modules'); 2912 2913 // Adding new fields to table course_module table. 2914 $field = new xmldb_field('completionpassgrade', XMLDB_TYPE_INTEGER, '1', null, 2915 XMLDB_NOTNULL, null, '0', 'completionexpected'); 2916 // Conditionally launch create table for course_completion_defaults. 2917 if (!$dbman->field_exists($table, $field)) { 2918 $dbman->add_field($table, $field); 2919 } 2920 2921 upgrade_main_savepoint(true, 2021100600.03); 2922 } 2923 2924 if ($oldversion < 2021100600.04) { 2925 // Define index itemtype-mod-inst-course (not unique) to be added to grade_items. 2926 $table = new xmldb_table('grade_items'); 2927 $index = new xmldb_index('itemtype-mod-inst-course', XMLDB_INDEX_NOTUNIQUE, 2928 ['itemtype', 'itemmodule', 'iteminstance', 'courseid']); 2929 2930 // Conditionally launch add index itemtype-mod-inst-course. 2931 if (!$dbman->index_exists($table, $index)) { 2932 $dbman->add_index($table, $index); 2933 } 2934 2935 // Main savepoint reached. 2936 upgrade_main_savepoint(true, 2021100600.04); 2937 } 2938 2939 if ($oldversion < 2021101900.01) { 2940 $table = new xmldb_table('reportbuilder_report'); 2941 2942 // Define field name to be added to reportbuilder_report. 2943 $field = new xmldb_field('name', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'id'); 2944 if (!$dbman->field_exists($table, $field)) { 2945 $dbman->add_field($table, $field); 2946 } 2947 2948 // Define field conditiondata to be added to reportbuilder_report. 2949 $field = new xmldb_field('conditiondata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'type'); 2950 if (!$dbman->field_exists($table, $field)) { 2951 $dbman->add_field($table, $field); 2952 } 2953 2954 // Define table reportbuilder_column to be created. 2955 $table = new xmldb_table('reportbuilder_column'); 2956 2957 // Adding fields to table reportbuilder_column. 2958 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2959 $table->add_field('reportid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2960 $table->add_field('uniqueidentifier', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 2961 $table->add_field('aggregation', XMLDB_TYPE_CHAR, '32', null, null, null, null); 2962 $table->add_field('heading', XMLDB_TYPE_CHAR, '255', null, null, null, null); 2963 $table->add_field('columnorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2964 $table->add_field('sortenabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 2965 $table->add_field('sortdirection', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, null); 2966 $table->add_field('sortorder', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 2967 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2968 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2969 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2970 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2971 2972 // Adding keys to table reportbuilder_column. 2973 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 2974 $table->add_key('reportid', XMLDB_KEY_FOREIGN, ['reportid'], 'reportbuilder_report', ['id']); 2975 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']); 2976 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']); 2977 2978 // Conditionally launch create table for reportbuilder_column. 2979 if (!$dbman->table_exists($table)) { 2980 $dbman->create_table($table); 2981 } 2982 2983 // Define table reportbuilder_filter to be created. 2984 $table = new xmldb_table('reportbuilder_filter'); 2985 2986 // Adding fields to table reportbuilder_filter. 2987 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2988 $table->add_field('reportid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2989 $table->add_field('uniqueidentifier', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 2990 $table->add_field('heading', XMLDB_TYPE_CHAR, '255', null, null, null, null); 2991 $table->add_field('iscondition', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 2992 $table->add_field('filterorder', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2993 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2994 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2995 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2996 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2997 2998 // Adding keys to table reportbuilder_filter. 2999 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3000 $table->add_key('reportid', XMLDB_KEY_FOREIGN, ['reportid'], 'reportbuilder_report', ['id']); 3001 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']); 3002 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']); 3003 3004 // Conditionally launch create table for reportbuilder_filter. 3005 if (!$dbman->table_exists($table)) { 3006 $dbman->create_table($table); 3007 } 3008 3009 // Main savepoint reached. 3010 upgrade_main_savepoint(true, 2021101900.01); 3011 } 3012 3013 if ($oldversion < 2021102600.01) { 3014 // Remove block_quiz_results (unless it has manually been added back). 3015 if (!file_exists($CFG->dirroot . '/blocks/quiz_result/block_quiz_results.php')) { 3016 // Delete instances. 3017 $instances = $DB->get_records_list('block_instances', 'blockname', ['quiz_results']); 3018 $instanceids = array_keys($instances); 3019 3020 if (!empty($instanceids)) { 3021 blocks_delete_instances($instanceids); 3022 } 3023 3024 // Delete the block from the block table. 3025 $DB->delete_records('block', array('name' => 'quiz_results')); 3026 3027 // Remove capabilities. 3028 capabilities_cleanup('block_quiz_results'); 3029 // Clean config. 3030 unset_all_config_for_plugin('block_quiz_results'); 3031 3032 // Remove Moodle-level quiz_results based capabilities. 3033 $capabilitiestoberemoved = ['block/quiz_results:addinstance']; 3034 // Delete any role_capabilities for the old roles. 3035 $DB->delete_records_list('role_capabilities', 'capability', $capabilitiestoberemoved); 3036 // Delete the capability itself. 3037 $DB->delete_records_list('capabilities', 'name', $capabilitiestoberemoved); 3038 } 3039 3040 upgrade_main_savepoint(true, 2021102600.01); 3041 } 3042 3043 if ($oldversion < 2021102900.02) { 3044 // If portfolio_boxnet is no longer present, remove it. 3045 if (!file_exists($CFG->dirroot . '/portfolio/boxnet/version.php')) { 3046 $instance = $DB->get_record('portfolio_instance', ['plugin' => 'boxnet']); 3047 if (!empty($instance)) { 3048 // Remove all records from portfolio_instance_config. 3049 $DB->delete_records('portfolio_instance_config', ['instance' => $instance->id]); 3050 // Remove all records from portfolio_instance_user. 3051 $DB->delete_records('portfolio_instance_user', ['instance' => $instance->id]); 3052 // Remove all records from portfolio_log. 3053 $DB->delete_records('portfolio_log', ['portfolio' => $instance->id]); 3054 // Remove all records from portfolio_tempdata. 3055 $DB->delete_records('portfolio_tempdata', ['instance' => $instance->id]); 3056 // Remove the record from the portfolio_instance table. 3057 $DB->delete_records('portfolio_instance', ['id' => $instance->id]); 3058 } 3059 3060 // Clean config. 3061 unset_all_config_for_plugin('portfolio_boxnet'); 3062 } 3063 3064 // If repository_boxnet is no longer present, remove it. 3065 if (!file_exists($CFG->dirroot . '/repository/boxnet/version.php')) { 3066 $instance = $DB->get_record('repository', ['type' => 'boxnet']); 3067 if (!empty($instance)) { 3068 // Remove all records from repository_instance_config table. 3069 $DB->delete_records('repository_instance_config', ['instanceid' => $instance->id]); 3070 // Remove all records from repository_instances table. 3071 $DB->delete_records('repository_instances', ['typeid' => $instance->id]); 3072 // Remove the record from the repository table. 3073 $DB->delete_records('repository', ['id' => $instance->id]); 3074 } 3075 3076 // Clean config. 3077 unset_all_config_for_plugin('repository_boxnet'); 3078 3079 // The boxnet repository plugin stores some config in 'boxnet' incorrectly. 3080 unset_all_config_for_plugin('boxnet'); 3081 3082 // Remove orphaned files. 3083 upgrade_delete_orphaned_file_records(); 3084 } 3085 3086 upgrade_main_savepoint(true, 2021102900.02); 3087 } 3088 3089 if ($oldversion < 2021110100.00) { 3090 3091 // Define table reportbuilder_audience to be created. 3092 $table = new xmldb_table('reportbuilder_audience'); 3093 3094 // Adding fields to table reportbuilder_audience. 3095 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3096 $table->add_field('reportid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3097 $table->add_field('classname', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 3098 $table->add_field('configdata', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); 3099 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3100 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3101 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3102 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3103 3104 // Adding keys to table reportbuilder_audience. 3105 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3106 $table->add_key('reportid', XMLDB_KEY_FOREIGN, ['reportid'], 'reportbuilder_report', ['id']); 3107 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']); 3108 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']); 3109 3110 // Conditionally launch create table for reportbuilder_audience. 3111 if (!$dbman->table_exists($table)) { 3112 $dbman->create_table($table); 3113 } 3114 3115 // Main savepoint reached. 3116 upgrade_main_savepoint(true, 2021110100.00); 3117 } 3118 3119 if ($oldversion < 2021110800.02) { 3120 // Define a field 'downloadcontent' in the 'course_modules' table. 3121 $table = new xmldb_table('course_modules'); 3122 $field = new xmldb_field('downloadcontent', XMLDB_TYPE_INTEGER, '1', null, null, null, 1, 'deletioninprogress'); 3123 3124 // Conditionally launch add field 'downloadcontent'. 3125 if (!$dbman->field_exists($table, $field)) { 3126 $dbman->add_field($table, $field); 3127 } 3128 3129 // Main savepoint reached. 3130 upgrade_main_savepoint(true, 2021110800.02); 3131 } 3132 3133 if ($oldversion < 2021110800.03) { 3134 3135 // Define field settingsdata to be added to reportbuilder_report. 3136 $table = new xmldb_table('reportbuilder_report'); 3137 $field = new xmldb_field('settingsdata', XMLDB_TYPE_TEXT, null, null, null, null, null, 'conditiondata'); 3138 3139 // Conditionally launch add field settingsdata. 3140 if (!$dbman->field_exists($table, $field)) { 3141 $dbman->add_field($table, $field); 3142 } 3143 3144 // Main savepoint reached. 3145 upgrade_main_savepoint(true, 2021110800.03); 3146 } 3147 3148 if ($oldversion < 2021111700.00) { 3149 $mycoursespage = new stdClass(); 3150 $mycoursespage->userid = null; 3151 $mycoursespage->name = '__courses'; 3152 $mycoursespage->private = 0; 3153 $mycoursespage->sortorder = 0; 3154 $DB->insert_record('my_pages', $mycoursespage); 3155 3156 upgrade_main_savepoint(true, 2021111700.00); 3157 } 3158 3159 if ($oldversion < 2021111700.01) { 3160 3161 // Define field uniquerows to be added to reportbuilder_report. 3162 $table = new xmldb_table('reportbuilder_report'); 3163 $field = new xmldb_field('uniquerows', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'type'); 3164 3165 // Conditionally launch add field uniquerows. 3166 if (!$dbman->field_exists($table, $field)) { 3167 $dbman->add_field($table, $field); 3168 } 3169 3170 // Main savepoint reached. 3171 upgrade_main_savepoint(true, 2021111700.01); 3172 } 3173 3174 if ($oldversion < 2021120100.01) { 3175 3176 // Get current configuration data. 3177 $currentcustomusermenuitems = str_replace(["\r\n", "\r"], "\n", $CFG->customusermenuitems); 3178 $lines = explode("\n", $currentcustomusermenuitems); 3179 $lines = array_map('trim', $lines); 3180 $calendarcustomusermenu = 'calendar,core_calendar|/calendar/view.php?view=month|i/calendar'; 3181 3182 if (!in_array($calendarcustomusermenu, $lines)) { 3183 // Add Calendar item to the menu. 3184 array_splice($lines, 1, 0, [$calendarcustomusermenu]); 3185 set_config('customusermenuitems', implode("\n", $lines)); 3186 } 3187 3188 // Main savepoint reached. 3189 upgrade_main_savepoint(true, 2021120100.01); 3190 } 3191 3192 if ($oldversion < 2021121400.01) { 3193 // The $CFG->grade_navmethod setting has been removed because it's not required anymore. This setting was used 3194 // to set the type of navigation (tabs or dropdown box) which will be displayed in gradebook. However, these 3195 // navigation methods are no longer used and replaced with tertiary navigation. 3196 unset_config('grade_navmethod'); 3197 3198 // Main savepoint reached. 3199 upgrade_main_savepoint(true, 2021121400.01); 3200 } 3201 3202 if ($oldversion < 2021121700.01) { 3203 // Get current support email setting value. 3204 $config = get_config('moodle', 'supportemail'); 3205 3206 // Check if support email setting is empty and then set it to null. 3207 // We must do that so the setting is displayed during the upgrade. 3208 if (empty($config)) { 3209 set_config('supportemail', null); 3210 } 3211 3212 // Main savepoint reached. 3213 upgrade_main_savepoint(true, 2021121700.01); 3214 } 3215 3216 if ($oldversion < 2021122100.00) { 3217 // Get current configuration data. 3218 $currentcustomusermenuitems = str_replace(["\r\n", "\r"], "\n", $CFG->customusermenuitems); 3219 3220 // The old default customusermenuitems config for 3.11 and below. 3221 $oldcustomusermenuitems = 'grades,grades|/grade/report/mygrades.php|t/grades 3222 calendar,core_calendar|/calendar/view.php?view=month|i/calendar 3223 messages,message|/message/index.php|t/message 3224 preferences,moodle|/user/preferences.php|t/preferences'; 3225 3226 // Check if the current customusermenuitems config matches the old customusermenuitems config. 3227 $samecustomusermenuitems = $currentcustomusermenuitems == $oldcustomusermenuitems; 3228 if ($samecustomusermenuitems) { 3229 // If the site is still using the old defaults, upgrade to the new default. 3230 $newcustomusermenuitems = 'profile,moodle|/user/profile.php 3231 grades,grades|/grade/report/mygrades.php 3232 calendar,core_calendar|/calendar/view.php?view=month 3233 privatefiles,moodle|/user/files.php'; 3234 // Set the new configuration back. 3235 set_config('customusermenuitems', $newcustomusermenuitems); 3236 } else { 3237 // If the site is not using the old defaults, only add necessary entries. 3238 $lines = preg_split('/\n/', $currentcustomusermenuitems, -1, PREG_SPLIT_NO_EMPTY); 3239 $lines = array_map(static function(string $line): string { 3240 // Previous format was "<langstring>|<url>[|<pixicon>]" - pix icon is no longer supported. 3241 $lineparts = explode('|', trim($line), 3); 3242 // Return first two parts of line. 3243 return implode('|', array_slice($lineparts, 0, 2)); 3244 }, $lines); 3245 3246 // Remove the Preference entry from the menu to prevent duplication 3247 // since it will be added again in user_get_user_navigation_info(). 3248 $lines = array_filter($lines, function($value) { 3249 return strpos($value, 'preferences,moodle|/user/preferences.php') === false; 3250 }); 3251 3252 $matches = preg_grep('/\|\/user\/files.php/i', $lines); 3253 if (!$matches) { 3254 // Add the Private files entry to the menu. 3255 $lines[] = 'privatefiles,moodle|/user/files.php'; 3256 } 3257 3258 $matches = preg_grep('/\|\/user\/profile.php/i', $lines); 3259 if (!$matches) { 3260 // Add the Profile entry to top of the menu. 3261 array_unshift($lines, 'profile,moodle|/user/profile.php'); 3262 } 3263 3264 // Set the new configuration back. 3265 set_config('customusermenuitems', implode("\n", $lines)); 3266 } 3267 3268 // Main savepoint reached. 3269 upgrade_main_savepoint(true, 2021122100.00); 3270 } 3271 3272 3273 if ($oldversion < 2021122100.01) { 3274 3275 // Define field heading to be added to reportbuilder_audience. 3276 $table = new xmldb_table('reportbuilder_audience'); 3277 $field = new xmldb_field('heading', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'reportid'); 3278 3279 // Conditionally launch add field heading. 3280 if (!$dbman->field_exists($table, $field)) { 3281 $dbman->add_field($table, $field); 3282 } 3283 3284 // Main savepoint reached. 3285 upgrade_main_savepoint(true, 2021122100.01); 3286 } 3287 3288 if ($oldversion < 2021122100.02) { 3289 3290 // Define table reportbuilder_schedule to be created. 3291 $table = new xmldb_table('reportbuilder_schedule'); 3292 3293 // Adding fields to table reportbuilder_schedule. 3294 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3295 $table->add_field('reportid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3296 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 3297 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1'); 3298 $table->add_field('audiences', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); 3299 $table->add_field('format', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 3300 $table->add_field('subject', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 3301 $table->add_field('message', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null); 3302 $table->add_field('messageformat', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3303 $table->add_field('userviewas', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3304 $table->add_field('timescheduled', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3305 $table->add_field('recurrence', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3306 $table->add_field('reportempty', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3307 $table->add_field('timelastsent', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3308 $table->add_field('timenextsend', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3309 $table->add_field('usercreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3310 $table->add_field('usermodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3311 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3312 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3313 3314 // Adding keys to table reportbuilder_schedule. 3315 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3316 $table->add_key('reportid', XMLDB_KEY_FOREIGN, ['reportid'], 'reportbuilder_report', ['id']); 3317 $table->add_key('userviewas', XMLDB_KEY_FOREIGN, ['userviewas'], 'user', ['id']); 3318 $table->add_key('usercreated', XMLDB_KEY_FOREIGN, ['usercreated'], 'user', ['id']); 3319 $table->add_key('usermodified', XMLDB_KEY_FOREIGN, ['usermodified'], 'user', ['id']); 3320 3321 // Conditionally launch create table for reportbuilder_schedule. 3322 if (!$dbman->table_exists($table)) { 3323 $dbman->create_table($table); 3324 } 3325 3326 // Main savepoint reached. 3327 upgrade_main_savepoint(true, 2021122100.02); 3328 } 3329 3330 if ($oldversion < 2021123000.01) { 3331 // The tool_admin_presets tables have been moved to core, because core_adminpresets component has been created, so 3332 // it can interact with the rest of core. 3333 // So the tool_admin_presetsXXX tables will be renamed to adminipresetsXXX if they exists; otherwise, they will be created. 3334 3335 $tooltable = new xmldb_table('tool_admin_presets'); 3336 $table = new xmldb_table('adminpresets'); 3337 if ($dbman->table_exists($tooltable)) { 3338 $dbman->rename_table($tooltable, 'adminpresets'); 3339 } else if (!$dbman->table_exists($table)) { 3340 // Adding fields to table adminpresets. 3341 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3342 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3343 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 3344 $table->add_field('comments', XMLDB_TYPE_TEXT, null, null, null, null, null); 3345 $table->add_field('site', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 3346 $table->add_field('author', XMLDB_TYPE_CHAR, '255', null, null, null, null); 3347 $table->add_field('moodleversion', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null); 3348 $table->add_field('moodlerelease', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 3349 $table->add_field('iscore', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 3350 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3351 $table->add_field('timeimported', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 3352 3353 // Adding keys to table adminpresets. 3354 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3355 3356 // Launch create table for adminpresets. 3357 $dbman->create_table($table); 3358 } 3359 3360 $tooltable = new xmldb_table('tool_admin_presets_it'); 3361 $table = new xmldb_table('adminpresets_it'); 3362 if ($dbman->table_exists($tooltable)) { 3363 $dbman->rename_table($tooltable, 'adminpresets_it'); 3364 } else if (!$dbman->table_exists($table)) { 3365 // Adding fields to table adminpresets_it. 3366 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3367 $table->add_field('adminpresetid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3368 $table->add_field('plugin', XMLDB_TYPE_CHAR, '100', null, null, null, null); 3369 $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 3370 $table->add_field('value', XMLDB_TYPE_TEXT, null, null, null, null, null); 3371 3372 // Adding keys to table adminpresets_it. 3373 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3374 3375 // Adding indexes to table adminpresets_it. 3376 $table->add_index('adminpresetid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetid']); 3377 3378 // Launch create table for adminpresets_it. 3379 $dbman->create_table($table); 3380 } 3381 3382 $tooltable = new xmldb_table('tool_admin_presets_it_a'); 3383 $table = new xmldb_table('adminpresets_it_a'); 3384 if ($dbman->table_exists($tooltable)) { 3385 $dbman->rename_table($tooltable, 'adminpresets_it_a'); 3386 } else if (!$dbman->table_exists($table)) { 3387 // Adding fields to table adminpresets_it_a. 3388 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3389 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3390 $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 3391 $table->add_field('value', XMLDB_TYPE_TEXT, null, null, null, null, null); 3392 3393 // Adding keys to table adminpresets_it_a. 3394 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3395 3396 // Adding indexes to table adminpresets_it_a. 3397 $table->add_index('itemid', XMLDB_INDEX_NOTUNIQUE, ['itemid']); 3398 3399 // Launch create table for adminpresets_it_a. 3400 $dbman->create_table($table); 3401 } 3402 3403 $tooltable = new xmldb_table('tool_admin_presets_app'); 3404 $table = new xmldb_table('adminpresets_app'); 3405 if ($dbman->table_exists($tooltable)) { 3406 $dbman->rename_table($tooltable, 'adminpresets_app'); 3407 } else if (!$dbman->table_exists($table)) { 3408 // Adding fields to table adminpresets_app. 3409 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3410 $table->add_field('adminpresetid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3411 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3412 $table->add_field('time', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3413 3414 // Adding keys to table adminpresets_app. 3415 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3416 3417 // Adding indexes to table adminpresets_app. 3418 $table->add_index('adminpresetid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetid']); 3419 3420 // Launch create table for adminpresets_app. 3421 $dbman->create_table($table); 3422 } 3423 3424 $tooltable = new xmldb_table('tool_admin_presets_app_it'); 3425 $table = new xmldb_table('adminpresets_app_it'); 3426 if ($dbman->table_exists($tooltable)) { 3427 $dbman->rename_table($tooltable, 'adminpresets_app_it'); 3428 } else if (!$dbman->table_exists($table)) { 3429 // Adding fields to table adminpresets_app_it. 3430 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3431 $table->add_field('adminpresetapplyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3432 $table->add_field('configlogid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3433 3434 // Adding keys to table adminpresets_app_it. 3435 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3436 3437 // Adding indexes to table adminpresets_app_it. 3438 $table->add_index('configlogid', XMLDB_INDEX_NOTUNIQUE, ['configlogid']); 3439 $table->add_index('adminpresetapplyid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetapplyid']); 3440 3441 // Launch create table for adminpresets_app_it. 3442 $dbman->create_table($table); 3443 } 3444 3445 $tooltable = new xmldb_table('tool_admin_presets_app_it_a'); 3446 $table = new xmldb_table('adminpresets_app_it_a'); 3447 if ($dbman->table_exists($tooltable)) { 3448 $dbman->rename_table($tooltable, 'adminpresets_app_it_a'); 3449 } else if (!$dbman->table_exists($table)) { 3450 // Adding fields to table adminpresets_app_it_a. 3451 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3452 $table->add_field('adminpresetapplyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3453 $table->add_field('configlogid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3454 $table->add_field('itemname', XMLDB_TYPE_CHAR, '100', null, null, null, null); 3455 3456 // Adding keys to table adminpresets_app_it_a. 3457 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3458 3459 // Adding indexes to table adminpresets_app_it_a. 3460 $table->add_index('configlogid', XMLDB_INDEX_NOTUNIQUE, ['configlogid']); 3461 $table->add_index('adminpresetapplyid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetapplyid']); 3462 3463 // Launch create table for adminpresets_app_it_a. 3464 $dbman->create_table($table); 3465 } 3466 3467 $tooltable = new xmldb_table('tool_admin_presets_plug'); 3468 $table = new xmldb_table('adminpresets_plug'); 3469 if ($dbman->table_exists($tooltable)) { 3470 $dbman->rename_table($tooltable, 'adminpresets_plug'); 3471 } else if (!$dbman->table_exists($table)) { 3472 // Adding fields to table adminpresets_plug. 3473 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3474 $table->add_field('adminpresetid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3475 $table->add_field('plugin', XMLDB_TYPE_CHAR, '100', null, null, null, null); 3476 $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 3477 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0'); 3478 3479 // Adding keys to table adminpresets_plug. 3480 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3481 3482 // Adding indexes to table adminpresets_plug. 3483 $table->add_index('adminpresetid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetid']); 3484 3485 // Launch create table for adminpresets_plug. 3486 $dbman->create_table($table); 3487 } 3488 3489 $tooltable = new xmldb_table('tool_admin_presets_app_plug'); 3490 $table = new xmldb_table('adminpresets_app_plug'); 3491 if ($dbman->table_exists($tooltable)) { 3492 $dbman->rename_table($tooltable, 'adminpresets_app_plug'); 3493 } else if (!$dbman->table_exists($table)) { 3494 // Adding fields to table adminpresets_app_plug. 3495 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3496 $table->add_field('adminpresetapplyid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 3497 $table->add_field('plugin', XMLDB_TYPE_CHAR, '100', null, null, null, null); 3498 $table->add_field('name', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 3499 $table->add_field('value', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0'); 3500 $table->add_field('oldvalue', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0'); 3501 3502 // Adding keys to table adminpresets_app_plug. 3503 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3504 3505 // Adding indexes to table adminpresets_app_plug. 3506 $table->add_index('adminpresetapplyid', XMLDB_INDEX_NOTUNIQUE, ['adminpresetapplyid']); 3507 3508 // Launch create table for adminpresets_app_plug. 3509 if (!$dbman->table_exists($table)) { 3510 $dbman->create_table($table); 3511 } 3512 } 3513 3514 if ($DB->count_records('adminpresets', ['iscore' => 1]) == 0) { 3515 // Create default core site admin presets. 3516 require_once($CFG->dirroot . '/admin/presets/classes/helper.php'); 3517 \core_adminpresets\helper::create_default_presets(); 3518 } 3519 3520 // Main savepoint reached. 3521 upgrade_main_savepoint(true, 2021123000.01); 3522 } 3523 3524 if ($oldversion < 2021123000.02) { 3525 // If exists, migrate sensiblesettings admin settings from tool_admin_preset to adminpresets. 3526 if (get_config('tool_admin_presets', 'sensiblesettings') !== false) { 3527 set_config('sensiblesettings', get_config('tool_admin_presets', 'sensiblesettings'), 'adminpresets'); 3528 unset_config('sensiblesettings', 'tool_admin_presets'); 3529 } 3530 3531 // Main savepoint reached. 3532 upgrade_main_savepoint(true, 2021123000.02); 3533 } 3534 3535 if ($oldversion < 2021123000.03) { 3536 // If exists, migrate lastpresetapplied setting from tool_admin_preset to adminpresets. 3537 if (get_config('tool_admin_presets', 'lastpresetapplied') !== false) { 3538 set_config('lastpresetapplied', get_config('tool_admin_presets', 'lastpresetapplied'), 'adminpresets'); 3539 unset_config('lastpresetapplied', 'tool_admin_presets'); 3540 } 3541 3542 // Main savepoint reached. 3543 upgrade_main_savepoint(true, 2021123000.03); 3544 } 3545 3546 if ($oldversion < 2022011100.01) { 3547 // The following blocks have been hidden by default, so they shouldn't be enabled in the Full core preset: Course/site 3548 // summary, RSS feeds, Self completion and Feedback. 3549 $params = ['name' => get_string('fullpreset', 'core_adminpresets')]; 3550 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 3551 3552 if (!$fullpreset) { 3553 // Full admin preset might have been created using the English name. 3554 $name = get_string_manager()->get_string('fullpreset', 'core_adminpresets', null, 'en'); 3555 $params['name'] = $name; 3556 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 3557 } 3558 if (!$fullpreset) { 3559 // We tried, but we didn't find full by name. Let's find a core preset that sets 'usecomments' setting to 1. 3560 $sql = "SELECT preset.* 3561 FROM {adminpresets} preset 3562 INNER JOIN {adminpresets_it} it ON preset.id = it.adminpresetid 3563 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0"; 3564 $params = ['name' => 'usecomments', 'value' => '1']; 3565 $fullpreset = $DB->get_record_sql($sql, $params); 3566 } 3567 3568 if ($fullpreset) { 3569 $blocknames = ['course_summary', 'feedback', 'rss_client', 'selfcompletion']; 3570 list($blocksinsql, $blocksinparams) = $DB->get_in_or_equal($blocknames); 3571 3572 // Remove entries from the adminpresets_app_plug table (in case the preset has been applied). 3573 $appliedpresets = $DB->get_records('adminpresets_app', ['adminpresetid' => $fullpreset->id], '', 'id'); 3574 if ($appliedpresets) { 3575 list($appsinsql, $appsinparams) = $DB->get_in_or_equal(array_keys($appliedpresets)); 3576 $sql = "adminpresetapplyid $appsinsql AND plugin='block' AND name $blocksinsql"; 3577 $params = array_merge($appsinparams, $blocksinparams); 3578 $DB->delete_records_select('adminpresets_app_plug', $sql, $params); 3579 } 3580 3581 // Remove entries for these blocks from the adminpresets_plug table. 3582 $sql = "adminpresetid = ? AND plugin='block' AND name $blocksinsql"; 3583 $params = array_merge([$fullpreset->id], $blocksinparams); 3584 $DB->delete_records_select('adminpresets_plug', $sql, $params); 3585 } 3586 3587 // Main savepoint reached. 3588 upgrade_main_savepoint(true, 2022011100.01); 3589 } 3590 3591 if ($oldversion < 2022012100.02) { 3592 // Migrate default message output config. 3593 $preferences = get_config('message'); 3594 3595 $treatedprefs = []; 3596 3597 foreach ($preferences as $preference => $value) { 3598 // Extract provider and preference name from the setting name. 3599 // Example name: airnotifier_provider_enrol_imsenterprise_imsenterprise_enrolment_permitted 3600 // Provider: airnotifier 3601 // Preference: enrol_imsenterprise_imsenterprise_enrolment_permitted. 3602 $providerparts = explode('_provider_', $preference); 3603 if (count($providerparts) <= 1) { 3604 continue; 3605 } 3606 3607 $provider = $providerparts[0]; 3608 $preference = $providerparts[1]; 3609 3610 // Extract and remove last part of the preference previously extracted: ie. permitted. 3611 $parts = explode('_', $preference); 3612 $key = array_pop($parts); 3613 3614 if (in_array($key, ['permitted', 'loggedin', 'loggedoff'])) { 3615 if ($key == 'permitted') { 3616 // We will use provider name instead of permitted. 3617 $key = $provider; 3618 } else { 3619 // Logged in and logged off values are a csv of the enabled providers. 3620 $value = explode(',', $value); 3621 } 3622 3623 // Join the rest of the parts: ie enrol_imsenterprise_imsenterprise_enrolment. 3624 $prefname = implode('_', $parts); 3625 3626 if (!isset($treatedprefs[$prefname])) { 3627 $treatedprefs[$prefname] = []; 3628 } 3629 3630 // Save the value with the selected key. 3631 $treatedprefs[$prefname][$key] = $value; 3632 } 3633 } 3634 3635 // Now take every preference previous treated and its values. 3636 foreach ($treatedprefs as $prefname => $values) { 3637 $enabled = []; // List of providers enabled for each preference. 3638 3639 // Enable if one of those is enabled. 3640 $loggedin = isset($values['loggedin']) ? $values['loggedin'] : []; 3641 foreach ($loggedin as $provider) { 3642 $enabled[$provider] = 1; 3643 } 3644 $loggedoff = isset($values['loggedoff']) ? $values['loggedoff'] : []; 3645 foreach ($loggedoff as $provider) { 3646 $enabled[$provider] = 1; 3647 } 3648 3649 // Do not treat those values again. 3650 unset($values['loggedin']); 3651 unset($values['loggedoff']); 3652 3653 // Translate rest of values coming from permitted "key". 3654 foreach ($values as $provider => $value) { 3655 $locked = false; 3656 3657 switch ($value) { 3658 case 'forced': 3659 // Provider is enabled by force. 3660 $enabled[$provider] = 1; 3661 $locked = true; 3662 break; 3663 case 'disallowed': 3664 // Provider is disabled by force. 3665 unset($enabled[$provider]); 3666 $locked = true; 3667 break; 3668 default: 3669 // Provider is not forced (permitted) or invalid values. 3670 } 3671 3672 // Save locked. 3673 if ($locked) { 3674 set_config($provider.'_provider_'.$prefname.'_locked', 1, 'message'); 3675 } else { 3676 set_config($provider.'_provider_'.$prefname.'_locked', 0, 'message'); 3677 } 3678 // Remove old value. 3679 unset_config($provider.'_provider_'.$prefname.'_permitted', 'message'); 3680 } 3681 3682 // Save the new values. 3683 $value = implode(',', array_keys($enabled)); 3684 set_config('message_provider_'.$prefname.'_enabled', $value, 'message'); 3685 // Remove old values. 3686 unset_config('message_provider_'.$prefname.'_loggedin', 'message'); 3687 unset_config('message_provider_'.$prefname.'_loggedoff', 'message'); 3688 } 3689 3690 // Migrate user preferences. ie merging message_provider_moodle_instantmessage_loggedoff with 3691 // message_provider_moodle_instantmessage_loggedin to message_provider_moodle_instantmessage_enabled. 3692 3693 $allrecordsloggedoff = $DB->sql_like('name', ':loggedoff'); 3694 $total = $DB->count_records_select( 3695 'user_preferences', 3696 $allrecordsloggedoff, 3697 ['loggedoff' => 'message_provider_%_loggedoff'] 3698 ); 3699 $i = 0; 3700 if ($total == 0) { 3701 $total = 1; // Avoid division by zero. 3702 } 3703 3704 // Show a progress bar. 3705 $pbar = new progress_bar('upgradeusernotificationpreferences', 500, true); 3706 $pbar->update($i, $total, "Upgrading user notifications preferences - $i/$total."); 3707 3708 // We're migrating provider per provider to reduce memory usage. 3709 $providers = $DB->get_records('message_providers', null, 'name'); 3710 foreach ($providers as $provider) { 3711 // 60 minutes to migrate each provider. 3712 upgrade_set_timeout(3600); 3713 $componentproviderbase = 'message_provider_'.$provider->component.'_'.$provider->name; 3714 3715 $loggedinname = $componentproviderbase.'_loggedin'; 3716 $loggedoffname = $componentproviderbase.'_loggedoff'; 3717 3718 // Change loggedin to enabled. 3719 $enabledname = $componentproviderbase.'_enabled'; 3720 $DB->set_field('user_preferences', 'name', $enabledname, ['name' => $loggedinname]); 3721 3722 $selectparams = [ 3723 'enabled' => $enabledname, 3724 'loggedoff' => $loggedoffname, 3725 ]; 3726 $sql = 'SELECT m1.id loggedoffid, m1.value as loggedoff, m2.value as enabled, m2.id as enabledid 3727 FROM 3728 (SELECT id, userid, value FROM {user_preferences} WHERE name = :loggedoff) m1 3729 LEFT JOIN 3730 (SELECT id, userid, value FROM {user_preferences} WHERE name = :enabled) m2 3731 ON m1.userid = m2.userid'; 3732 3733 while (($rs = $DB->get_recordset_sql($sql, $selectparams, 0, 1000)) && $rs->valid()) { 3734 // 10 minutes for every chunk. 3735 upgrade_set_timeout(600); 3736 3737 $deleterecords = []; 3738 $changename = []; 3739 $changevalue = []; // Multidimensional array with possible values as key to reduce SQL queries. 3740 foreach ($rs as $record) { 3741 if (empty($record->enabledid)) { 3742 // Enabled does not exists, change the name. 3743 $changename[] = $record->loggedoffid; 3744 } else if ($record->enabledid != $record->loggedoff) { 3745 // Exist and values differ (checked on SQL), update the enabled record. 3746 3747 if ($record->enabled != 'none' && !empty($record->enabled)) { 3748 $enabledvalues = explode(',', $record->enabled); 3749 } else { 3750 $enabledvalues = []; 3751 } 3752 3753 if ($record->loggedoff != 'none' && !empty($record->loggedoff)) { 3754 $loggedoffvalues = explode(',', $record->loggedoff); 3755 } else { 3756 $loggedoffvalues = []; 3757 } 3758 3759 $values = array_unique(array_merge($enabledvalues, $loggedoffvalues)); 3760 sort($values); 3761 3762 $newvalue = empty($values) ? 'none' : implode(',', $values); 3763 if (!isset($changevalue[$newvalue])) { 3764 $changevalue[$newvalue] = []; 3765 } 3766 $changevalue[$newvalue][] = $record->enabledid; 3767 3768 $deleterecords[] = $record->loggedoffid; 3769 } else { 3770 // They are the same, just delete loggedoff one. 3771 $deleterecords[] = $record->loggedoffid; 3772 } 3773 $i++; 3774 } 3775 $rs->close(); 3776 3777 // Commit the changes. 3778 if (!empty($changename)) { 3779 $changenameparams = [ 3780 'name' => $loggedoffname, 3781 ]; 3782 $changenameselect = 'name = :name AND id IN (' . implode(',', $changename) . ')'; 3783 $DB->set_field_select('user_preferences', 'name', $enabledname, $changenameselect, $changenameparams); 3784 } 3785 3786 if (!empty($changevalue)) { 3787 $changevalueparams = [ 3788 'name' => $enabledname, 3789 ]; 3790 foreach ($changevalue as $value => $ids) { 3791 $changevalueselect = 'name = :name AND id IN (' . implode(',', $ids) . ')'; 3792 $DB->set_field_select('user_preferences', 'value', $value, $changevalueselect, $changevalueparams); 3793 } 3794 } 3795 3796 if (!empty($deleterecords)) { 3797 $deleteparams = [ 3798 'name' => $loggedoffname, 3799 ]; 3800 $deleteselect = 'name = :name AND id IN (' . implode(',', $deleterecords) . ')'; 3801 $DB->delete_records_select('user_preferences', $deleteselect, $deleteparams); 3802 } 3803 3804 // Update progress. 3805 $pbar->update($i, $total, "Upgrading user notifications preferences - $i/$total."); 3806 } 3807 $rs->close(); 3808 3809 // Delete the rest of loggedoff values (that are equal than enabled). 3810 $deleteparams = [ 3811 'name' => $loggedoffname, 3812 ]; 3813 $deleteselect = 'name = :name'; 3814 $i += $DB->count_records_select('user_preferences', $deleteselect, $deleteparams); 3815 $DB->delete_records_select('user_preferences', $deleteselect, $deleteparams); 3816 3817 // Update progress. 3818 $pbar->update($i, $total, "Upgrading user notifications preferences - $i/$total."); 3819 } 3820 3821 core_plugin_manager::reset_caches(); 3822 3823 // Delete the orphan records. 3824 $allrecordsparams = ['loggedin' => 'message_provider_%_loggedin', 'loggedoff' => 'message_provider_%_loggedoff']; 3825 $allrecordsloggedin = $DB->sql_like('name', ':loggedin'); 3826 $allrecordsloggedinoffsql = "$allrecordsloggedin OR $allrecordsloggedoff"; 3827 $DB->delete_records_select('user_preferences', $allrecordsloggedinoffsql, $allrecordsparams); 3828 3829 // Update progress. 3830 $pbar->update($total, $total, "Upgrading user notifications preferences - $total/$total."); 3831 3832 upgrade_main_savepoint(true, 2022012100.02); 3833 } 3834 3835 // Introduce question versioning to core. 3836 // First, create the new tables. 3837 if ($oldversion < 2022020200.01) { 3838 // Define table question_bank_entries to be created. 3839 $table = new xmldb_table('question_bank_entries'); 3840 3841 // Adding fields to table question_bank_entries. 3842 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3843 $table->add_field('questioncategoryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0); 3844 $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null); 3845 $table->add_field('ownerid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 3846 3847 // Adding keys to table question_bank_entries. 3848 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3849 $table->add_key('questioncategoryid', XMLDB_KEY_FOREIGN, ['questioncategoryid'], 'question_categories', ['id']); 3850 $table->add_key('ownerid', XMLDB_KEY_FOREIGN, ['ownerid'], 'user', ['id']); 3851 3852 // Conditionally launch create table for question_bank_entries. 3853 if (!$dbman->table_exists($table)) { 3854 $dbman->create_table($table); 3855 } 3856 3857 // Create category id and id number index. 3858 $index = new xmldb_index('categoryidnumber', XMLDB_INDEX_UNIQUE, ['questioncategoryid', 'idnumber']); 3859 3860 // Conditionally launch add index categoryidnumber. 3861 if (!$dbman->index_exists($table, $index)) { 3862 $dbman->add_index($table, $index); 3863 } 3864 3865 // Define table question_versions to be created. 3866 $table = new xmldb_table('question_versions'); 3867 3868 // Adding fields to table question_versions. 3869 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3870 $table->add_field('questionbankentryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0); 3871 $table->add_field('version', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 1); 3872 $table->add_field('questionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0); 3873 $table->add_field('status', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, 'ready'); 3874 3875 // Adding keys to table question_versions. 3876 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3877 $table->add_key('questionbankentryid', XMLDB_KEY_FOREIGN, ['questionbankentryid'], 'question_bank_entries', ['id']); 3878 $table->add_key('questionid', XMLDB_KEY_FOREIGN, ['questionid'], 'question', ['id']); 3879 3880 // Conditionally launch create table for question_versions. 3881 if (!$dbman->table_exists($table)) { 3882 $dbman->create_table($table); 3883 } 3884 3885 // Define table question_references to be created. 3886 $table = new xmldb_table('question_references'); 3887 3888 // Adding fields to table question_references. 3889 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3890 $table->add_field('usingcontextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0); 3891 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null); 3892 $table->add_field('questionarea', XMLDB_TYPE_CHAR, '50', null, null, null, null); 3893 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 3894 $table->add_field('questionbankentryid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0); 3895 $table->add_field('version', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 3896 3897 // Adding keys to table question_references. 3898 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3899 $table->add_key('usingcontextid', XMLDB_KEY_FOREIGN, ['usingcontextid'], 'context', ['id']); 3900 $table->add_key('questionbankentryid', XMLDB_KEY_FOREIGN, ['questionbankentryid'], 'question_bank_entries', ['id']); 3901 3902 // Conditionally launch create table for question_references. 3903 if (!$dbman->table_exists($table)) { 3904 $dbman->create_table($table); 3905 } 3906 3907 // Define table question_set_references to be created. 3908 $table = new xmldb_table('question_set_references'); 3909 3910 // Adding fields to table question_set_references. 3911 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 3912 $table->add_field('usingcontextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0); 3913 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, null, null, null); 3914 $table->add_field('questionarea', XMLDB_TYPE_CHAR, '50', null, null, null, null); 3915 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 3916 $table->add_field('questionscontextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, 0); 3917 $table->add_field('filtercondition', XMLDB_TYPE_TEXT, null, null, null, null, null); 3918 3919 // Adding keys to table question_set_references. 3920 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 3921 $table->add_key('usingcontextid', XMLDB_KEY_FOREIGN, ['usingcontextid'], 'context', ['id']); 3922 $table->add_key('questionscontextid', XMLDB_KEY_FOREIGN, ['questionscontextid'], 'context', ['id']); 3923 3924 // Conditionally launch create table for question_set_references. 3925 if (!$dbman->table_exists($table)) { 3926 $dbman->create_table($table); 3927 } 3928 3929 // Main savepoint reached. 3930 upgrade_main_savepoint(true, 2022020200.01); 3931 } 3932 3933 if ($oldversion < 2022020200.02) { 3934 // Define a new temporary field in the question_bank_entries tables. 3935 // Creating temporary field questionid to populate the data in question version table. 3936 // This will make sure the appropriate question id is inserted the version table without making any complex joins. 3937 $table = new xmldb_table('question_bank_entries'); 3938 $field = new xmldb_field('questionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL); 3939 if (!$dbman->field_exists($table, $field)) { 3940 $dbman->add_field($table, $field); 3941 } 3942 3943 $transaction = $DB->start_delegated_transaction(); 3944 upgrade_set_timeout(3600); 3945 // Create the data for the question_bank_entries table with, including the new temporary field. 3946 $sql = <<<EOF 3947 INSERT INTO {question_bank_entries} 3948 (questionid, questioncategoryid, idnumber, ownerid) 3949 SELECT id, category, idnumber, createdby 3950 FROM {question} q 3951 EOF; 3952 3953 // Inserting question_bank_entries data. 3954 $DB->execute($sql); 3955 3956 $transaction->allow_commit(); 3957 3958 // Main savepoint reached. 3959 upgrade_main_savepoint(true, 2022020200.02); 3960 } 3961 3962 if ($oldversion < 2022020200.03) { 3963 $transaction = $DB->start_delegated_transaction(); 3964 upgrade_set_timeout(3600); 3965 // Create the question_versions using that temporary field. 3966 $sql = <<<EOF 3967 INSERT INTO {question_versions} 3968 (questionbankentryid, questionid, status) 3969 SELECT 3970 qbe.id, 3971 q.id, 3972 CASE 3973 WHEN q.hidden > 0 THEN 'hidden' 3974 ELSE 'ready' 3975 END 3976 FROM {question_bank_entries} qbe 3977 INNER JOIN {question} q ON qbe.questionid = q.id 3978 EOF; 3979 3980 // Inserting question_versions data. 3981 $DB->execute($sql); 3982 3983 $transaction->allow_commit(); 3984 3985 // Dropping temporary field questionid. 3986 $table = new xmldb_table('question_bank_entries'); 3987 $field = new xmldb_field('questionid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL); 3988 if ($dbman->field_exists($table, $field)) { 3989 $dbman->drop_field($table, $field); 3990 } 3991 3992 // Main savepoint reached. 3993 upgrade_main_savepoint(true, 2022020200.03); 3994 } 3995 3996 if ($oldversion < 2022020200.04) { 3997 $transaction = $DB->start_delegated_transaction(); 3998 upgrade_set_timeout(3600); 3999 // Create the base data for the random questions in the set_references table. 4000 // This covers most of the hard work in one go. 4001 $concat = $DB->sql_concat("'{\"questioncategoryid\":\"'", 'q.category', "'\",\"includingsubcategories\":\"'", 4002 'qs.includingsubcategories', "'\"}'"); 4003 $sql = <<<EOF 4004 INSERT INTO {question_set_references} 4005 (usingcontextid, component, questionarea, itemid, questionscontextid, filtercondition) 4006 SELECT 4007 c.id, 4008 'mod_quiz', 4009 'slot', 4010 qs.id, 4011 qc.contextid, 4012 $concat 4013 FROM {question} q 4014 INNER JOIN {quiz_slots} qs on q.id = qs.questionid 4015 INNER JOIN {course_modules} cm ON cm.instance = qs.quizid AND cm.module = :quizmoduleid 4016 INNER JOIN {context} c ON cm.id = c.instanceid AND c.contextlevel = :contextmodule 4017 INNER JOIN {question_categories} qc ON qc.id = q.category 4018 WHERE q.qtype = :random 4019 EOF; 4020 4021 // Inserting question_set_references data. 4022 $DB->execute($sql, [ 4023 'quizmoduleid' => $DB->get_field('modules', 'id', ['name' => 'quiz']), 4024 'contextmodule' => CONTEXT_MODULE, 4025 'random' => 'random', 4026 ]); 4027 4028 $transaction->allow_commit(); 4029 4030 // Main savepoint reached. 4031 upgrade_main_savepoint(true, 2022020200.04); 4032 } 4033 4034 if ($oldversion < 2022020200.05) { 4035 $transaction = $DB->start_delegated_transaction(); 4036 upgrade_set_timeout(3600); 4037 4038 // Count all the slot tags to be migrated (for progress bar). 4039 $total = $DB->count_records('quiz_slot_tags'); 4040 $pbar = new progress_bar('migratequestiontags', 1000, true); 4041 $i = 0; 4042 // Updating slot_tags for random question tags. 4043 // Now fetch any quiz slot tags and update those slot details into the question_set_references. 4044 $slottags = $DB->get_recordset('quiz_slot_tags', [], 'slotid ASC'); 4045 4046 $tagstrings = []; 4047 $lastslot = null; 4048 $runinsert = function (int $lastslot, array $tagstrings) use ($DB) { 4049 $conditiondata = $DB->get_field('question_set_references', 'filtercondition', 4050 ['itemid' => $lastslot, 'component' => 'mod_quiz', 'questionarea' => 'slot']); 4051 4052 // It is possible to have leftover tags in the database, without a corresponding 4053 // slot, because of an old bugs (e.g. MDL-76193). Therefore, if the slot is not found, 4054 // we can safely discard these tags. 4055 if (!empty($conditiondata)) { 4056 $condition = json_decode($conditiondata); 4057 $condition->tags = $tagstrings; 4058 $DB->set_field('question_set_references', 'filtercondition', json_encode($condition), 4059 ['itemid' => $lastslot, 'component' => 'mod_quiz', 'questionarea' => 'slot']); 4060 } 4061 }; 4062 4063 foreach ($slottags as $tag) { 4064 upgrade_set_timeout(3600); 4065 if ($lastslot && $tag->slotid != $lastslot) { 4066 if (!empty($tagstrings)) { 4067 // Insert the data. 4068 $runinsert($lastslot, $tagstrings); 4069 } 4070 // Prepare for the next slot id. 4071 $tagstrings = []; 4072 } 4073 4074 $lastslot = $tag->slotid; 4075 $tagstrings[] = "{$tag->tagid},{$tag->tagname}"; 4076 // Update progress. 4077 $i++; 4078 $pbar->update($i, $total, "Migrating question tags - $i/$total."); 4079 } 4080 if ($tagstrings) { 4081 $runinsert($lastslot, $tagstrings); 4082 } 4083 $slottags->close(); 4084 4085 $transaction->allow_commit(); 4086 // Main savepoint reached. 4087 upgrade_main_savepoint(true, 2022020200.05); 4088 } 4089 4090 if ($oldversion < 2022020200.06) { 4091 $transaction = $DB->start_delegated_transaction(); 4092 upgrade_set_timeout(3600); 4093 // Create question_references record for each question. 4094 // Except if qtype is random. That case is handled by question_set_reference. 4095 $sql = "INSERT INTO {question_references} 4096 (usingcontextid, component, questionarea, itemid, questionbankentryid) 4097 SELECT c.id, 'mod_quiz', 'slot', qs.id, qv.questionbankentryid 4098 FROM {question} q 4099 JOIN {question_versions} qv ON q.id = qv.questionid 4100 JOIN {quiz_slots} qs ON q.id = qs.questionid 4101 JOIN {modules} m ON m.name = 'quiz' 4102 JOIN {course_modules} cm ON cm.module = m.id AND cm.instance = qs.quizid 4103 JOIN {context} c ON c.instanceid = cm.id AND c.contextlevel = " . CONTEXT_MODULE . " 4104 WHERE q.qtype <> 'random'"; 4105 4106 // Inserting question_references data. 4107 $DB->execute($sql); 4108 4109 $transaction->allow_commit(); 4110 // Main savepoint reached. 4111 upgrade_main_savepoint(true, 2022020200.06); 4112 } 4113 4114 // Finally, drop fields from question table. 4115 if ($oldversion < 2022020200.07) { 4116 // Define fields to be dropped from questions. 4117 $table = new xmldb_table('question'); 4118 4119 $field = new xmldb_field('version'); 4120 // Conditionally launch drop field version. 4121 if ($dbman->field_exists($table, $field)) { 4122 $dbman->drop_field($table, $field); 4123 } 4124 4125 $field = new xmldb_field('hidden'); 4126 // Conditionally launch drop field hidden. 4127 if ($dbman->field_exists($table, $field)) { 4128 $dbman->drop_field($table, $field); 4129 } 4130 4131 // Define index categoryidnumber (not unique) to be dropped form question. 4132 $index = new xmldb_index('categoryidnumber', XMLDB_INDEX_UNIQUE, ['category', 'idnumber']); 4133 4134 // Conditionally launch drop index categoryidnumber. 4135 if ($dbman->index_exists($table, $index)) { 4136 $dbman->drop_index($table, $index); 4137 } 4138 4139 // Define key category (foreign) to be dropped form questions. 4140 $key = new xmldb_key('category', XMLDB_KEY_FOREIGN, ['category'], 'question_categories', ['id']); 4141 4142 // Launch drop key category. 4143 $dbman->drop_key($table, $key); 4144 4145 $field = new xmldb_field('idnumber'); 4146 // Conditionally launch drop field idnumber. 4147 if ($dbman->field_exists($table, $field)) { 4148 $dbman->drop_field($table, $field); 4149 } 4150 4151 $field = new xmldb_field('category'); 4152 // Conditionally launch drop field category. 4153 if ($dbman->field_exists($table, $field)) { 4154 $dbman->drop_field($table, $field); 4155 } 4156 4157 // Main savepoint reached. 4158 upgrade_main_savepoint(true, 2022020200.07); 4159 } 4160 4161 if ($oldversion < 2022021100.01) { 4162 $sql = "SELECT preset.* 4163 FROM {adminpresets} preset 4164 INNER JOIN {adminpresets_it} it ON preset.id = it.adminpresetid 4165 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0"; 4166 // Some settings and plugins have been added/removed to the Starter and Full preset. Add them to the core presets if 4167 // they haven't been included yet. 4168 $params = ['name' => get_string('starterpreset', 'core_adminpresets'), 'iscore' => 1]; 4169 $starterpreset = $DB->get_record('adminpresets', $params); 4170 if (!$starterpreset) { 4171 // Starter admin preset might have been created using the English name. 4172 $name = get_string_manager()->get_string('starterpreset', 'core_adminpresets', null, 'en'); 4173 $params['name'] = $name; 4174 $starterpreset = $DB->get_record('adminpresets', $params); 4175 } 4176 if (!$starterpreset) { 4177 // We tried, but we didn't find starter by name. Let's find a core preset that sets 'usecomments' setting to 0. 4178 $params = ['name' => 'usecomments', 'value' => '0']; 4179 $starterpreset = $DB->get_record_sql($sql, $params); 4180 } 4181 4182 $params = ['name' => get_string('fullpreset', 'core_adminpresets')]; 4183 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 4184 if (!$fullpreset) { 4185 // Full admin preset might have been created using the English name. 4186 $name = get_string_manager()->get_string('fullpreset', 'core_adminpresets', null, 'en'); 4187 $params['name'] = $name; 4188 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 4189 } 4190 if (!$fullpreset) { 4191 // We tried, but we didn't find full by name. Let's find a core preset that sets 'usecomments' setting to 1. 4192 $params = ['name' => 'usecomments', 'value' => '1']; 4193 $fullpreset = $DB->get_record_sql($sql, $params); 4194 } 4195 4196 $settings = [ 4197 // Settings. Hide Guest login button for Starter preset (and back to show for Full). 4198 [ 4199 'presetid' => $starterpreset->id, 4200 'plugin' => 'none', 4201 'name' => 'guestloginbutton', 4202 'value' => '0', 4203 ], 4204 [ 4205 'presetid' => $fullpreset->id, 4206 'plugin' => 'none', 4207 'name' => 'guestloginbutton', 4208 'value' => '1', 4209 ], 4210 // Settings. Set Activity chooser tabs to "Starred, All, Recommended"(1) for Starter and back it to default(0) for Full. 4211 [ 4212 'presetid' => $starterpreset->id, 4213 'plugin' => 'none', 4214 'name' => 'activitychoosertabmode', 4215 'value' => '1', 4216 ], 4217 [ 4218 'presetid' => $fullpreset->id, 4219 'plugin' => 'none', 4220 'name' => 'activitychoosertabmode', 4221 'value' => '0', 4222 ], 4223 ]; 4224 foreach ($settings as $notused => $setting) { 4225 $params = ['adminpresetid' => $setting['presetid'], 'plugin' => $setting['plugin'], 'name' => $setting['name']]; 4226 if (!$DB->record_exists('adminpresets_it', $params)) { 4227 $record = new \stdClass(); 4228 $record->adminpresetid = $setting['presetid']; 4229 $record->plugin = $setting['plugin']; 4230 $record->name = $setting['name']; 4231 $record->value = $setting['value']; 4232 $DB->insert_record('adminpresets_it', $record); 4233 } 4234 } 4235 4236 $plugins = [ 4237 // Plugins. Blocks. Disable/enable Online users, Recently accessed courses and Starred courses. 4238 [ 4239 'presetid' => $starterpreset->id, 4240 'plugin' => 'block', 4241 'name' => 'online_users', 4242 'enabled' => '0', 4243 ], 4244 [ 4245 'presetid' => $fullpreset->id, 4246 'plugin' => 'block', 4247 'name' => 'online_users', 4248 'enabled' => '1', 4249 ], 4250 [ 4251 'presetid' => $starterpreset->id, 4252 'plugin' => 'block', 4253 'name' => 'recentlyaccessedcourses', 4254 'enabled' => '0', 4255 ], 4256 [ 4257 'presetid' => $fullpreset->id, 4258 'plugin' => 'block', 4259 'name' => 'recentlyaccessedcourses', 4260 'enabled' => '1', 4261 ], 4262 [ 4263 'presetid' => $starterpreset->id, 4264 'plugin' => 'block', 4265 'name' => 'starredcourses', 4266 'enabled' => '0', 4267 ], 4268 [ 4269 'presetid' => $fullpreset->id, 4270 'plugin' => 'block', 4271 'name' => 'starredcourses', 4272 'enabled' => '1', 4273 ], 4274 // Plugins. Enrolments. Disable/enable Guest access. 4275 [ 4276 'presetid' => $starterpreset->id, 4277 'plugin' => 'enrol', 4278 'name' => 'guest', 4279 'enabled' => '0', 4280 ], 4281 [ 4282 'presetid' => $fullpreset->id, 4283 'plugin' => 'enrol', 4284 'name' => 'guest', 4285 'enabled' => '1', 4286 ], 4287 ]; 4288 foreach ($plugins as $notused => $plugin) { 4289 $params = ['adminpresetid' => $plugin['presetid'], 'plugin' => $plugin['plugin'], 'name' => $plugin['name']]; 4290 if (!$DB->record_exists('adminpresets_plug', $params)) { 4291 $record = new \stdClass(); 4292 $record->adminpresetid = $plugin['presetid']; 4293 $record->plugin = $plugin['plugin']; 4294 $record->name = $plugin['name']; 4295 $record->enabled = $plugin['enabled']; 4296 $DB->insert_record('adminpresets_plug', $record); 4297 } 4298 } 4299 4300 // Settings: Remove customusermenuitems setting from Starter and Full presets. 4301 $sql = "(adminpresetid = ? OR adminpresetid = ?) AND plugin = 'none' AND name = 'customusermenuitems'"; 4302 $params = [$starterpreset->id, $fullpreset->id]; 4303 $DB->delete_records_select('adminpresets_it', $sql, $params); 4304 4305 // Plugins. Question types. Re-enable Description and Essay for Starter. 4306 $sql = "(adminpresetid = ? OR adminpresetid = ?) AND plugin = 'qtype' AND (name = 'description' OR name = 'essay')"; 4307 $DB->delete_records_select('adminpresets_plug', $sql, $params); 4308 4309 // Main savepoint reached. 4310 upgrade_main_savepoint(true, 2022021100.01); 4311 4312 } 4313 4314 if ($oldversion < 2022021100.02) { 4315 $table = new xmldb_table('task_scheduled'); 4316 4317 // Changing precision of field minute on table task_scheduled to (200). 4318 $field = new xmldb_field('minute', XMLDB_TYPE_CHAR, '200', null, XMLDB_NOTNULL, null, null, 'blocking'); 4319 $dbman->change_field_precision($table, $field); 4320 // Changing precision of field hour on table task_scheduled to (70). 4321 $field = new xmldb_field('hour', XMLDB_TYPE_CHAR, '70', null, XMLDB_NOTNULL, null, null, 'minute'); 4322 $dbman->change_field_precision($table, $field); 4323 // Changing precision of field day on table task_scheduled to (90). 4324 $field = new xmldb_field('day', XMLDB_TYPE_CHAR, '90', null, XMLDB_NOTNULL, null, null, 'hour'); 4325 $dbman->change_field_precision($table, $field); 4326 // Changing precision of field month on table task_scheduled to (30). 4327 $field = new xmldb_field('month', XMLDB_TYPE_CHAR, '30', null, XMLDB_NOTNULL, null, null, 'day'); 4328 $dbman->change_field_precision($table, $field); 4329 4330 // Main savepoint reached. 4331 upgrade_main_savepoint(true, 2022021100.02); 4332 } 4333 4334 if ($oldversion < 2022022600.01) { 4335 // Get all processor and existing preferences. 4336 $processors = $DB->get_records('message_processors'); 4337 $providers = $DB->get_records('message_providers', null, '', 'id, name, component'); 4338 $existingpreferences = get_config('message'); 4339 4340 foreach ($processors as $processor) { 4341 foreach ($providers as $provider) { 4342 // Setting default preference name. 4343 $componentproviderbase = $provider->component . '_' . $provider->name; 4344 $preferencename = $processor->name.'_provider_'.$componentproviderbase.'_locked'; 4345 // If we do not have this setting yet, set it to 0. 4346 if (!isset($existingpreferences->{$preferencename})) { 4347 set_config($preferencename, 0, 'message'); 4348 } 4349 } 4350 } 4351 4352 upgrade_main_savepoint(true, 2022022600.01); 4353 } 4354 4355 if ($oldversion < 2022030100.00) { 4356 $sql = "SELECT preset.* 4357 FROM {adminpresets} preset 4358 INNER JOIN {adminpresets_it} it ON preset.id = it.adminpresetid 4359 WHERE it.name = :name AND it.value = :value AND preset.iscore > 0"; 4360 4361 $name = get_string('starterpreset', 'core_adminpresets'); 4362 $params = ['name' => $name, 'iscore' => 1]; 4363 $starterpreset = $DB->get_record('adminpresets', $params); 4364 if (!$starterpreset) { 4365 // Starter admin preset might have been created using the English name. Let's change it to current language. 4366 $englishname = get_string_manager()->get_string('starterpreset', 'core_adminpresets', null, 'en'); 4367 $params['name'] = $englishname; 4368 $starterpreset = $DB->get_record('adminpresets', $params); 4369 } 4370 if (!$starterpreset) { 4371 // We tried, but we didn't find starter by name. Let's find a core preset that sets 'usecomments' setting to 0. 4372 $params = ['name' => 'usecomments', 'value' => '0']; 4373 $starterpreset = $DB->get_record_sql($sql, $params); 4374 } 4375 // The iscore field is already 1 for starterpreset, so we don't need to change it. 4376 // We only need to update the name and comment in case they are different to current language strings. 4377 if ($starterpreset && $starterpreset->name != $name) { 4378 $starterpreset->name = $name; 4379 $starterpreset->comments = get_string('starterpresetdescription', 'core_adminpresets'); 4380 $DB->update_record('adminpresets', $starterpreset); 4381 } 4382 4383 // Let's mark Full admin presets with current FULL_PRESETS value and change the name to current language. 4384 $name = get_string('fullpreset', 'core_adminpresets'); 4385 $params = ['name' => $name]; 4386 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 4387 if (!$fullpreset) { 4388 // Full admin preset might have been created using the English name. 4389 $englishname = get_string_manager()->get_string('fullpreset', 'core_adminpresets', null, 'en'); 4390 $params['name'] = $englishname; 4391 $fullpreset = $DB->get_record_select('adminpresets', 'name = :name and iscore > 0', $params); 4392 } 4393 if (!$fullpreset) { 4394 // We tried, but we didn't find full by name. Let's find a core preset that sets 'usecomments' setting to 1. 4395 $params = ['name' => 'usecomments', 'value' => '1']; 4396 $fullpreset = $DB->get_record_sql($sql, $params); 4397 } 4398 if ($fullpreset) { 4399 // We need to update iscore field value, whether the name is the same or not. 4400 $fullpreset->name = $name; 4401 $fullpreset->comments = get_string('fullpresetdescription', 'core_adminpresets'); 4402 $fullpreset->iscore = 2; 4403 $DB->update_record('adminpresets', $fullpreset); 4404 4405 // We are applying again changes made on 2022011100.01 upgrading step because of MDL-73953 bug. 4406 $blocknames = ['course_summary', 'feedback', 'rss_client', 'selfcompletion']; 4407 list($blocksinsql, $blocksinparams) = $DB->get_in_or_equal($blocknames); 4408 4409 // Remove entries from the adminpresets_app_plug table (in case the preset has been applied). 4410 $appliedpresets = $DB->get_records('adminpresets_app', ['adminpresetid' => $fullpreset->id], '', 'id'); 4411 if ($appliedpresets) { 4412 list($appsinsql, $appsinparams) = $DB->get_in_or_equal(array_keys($appliedpresets)); 4413 $sql = "adminpresetapplyid $appsinsql AND plugin='block' AND name $blocksinsql"; 4414 $params = array_merge($appsinparams, $blocksinparams); 4415 $DB->delete_records_select('adminpresets_app_plug', $sql, $params); 4416 } 4417 4418 // Remove entries for these blocks from the adminpresets_plug table. 4419 $sql = "adminpresetid = ? AND plugin='block' AND name $blocksinsql"; 4420 $params = array_merge([$fullpreset->id], $blocksinparams); 4421 $DB->delete_records_select('adminpresets_plug', $sql, $params); 4422 } 4423 4424 // Main savepoint reached. 4425 upgrade_main_savepoint(true, 2022030100.00); 4426 } 4427 4428 if ($oldversion < 2022031100.01) { 4429 $reportsusermenuitem = 'reports,core_reportbuilder|/reportbuilder/index.php'; 4430 upgrade_add_item_to_usermenu($reportsusermenuitem); 4431 // Main savepoint reached. 4432 upgrade_main_savepoint(true, 2022031100.01); 4433 } 4434 4435 if ($oldversion < 2022032200.01) { 4436 4437 // Define index to be added to question_references. 4438 $table = new xmldb_table('question_references'); 4439 $index = new xmldb_index('context-component-area-itemid', XMLDB_INDEX_UNIQUE, 4440 ['usingcontextid', 'component', 'questionarea', 'itemid']); 4441 4442 // Conditionally launch add field id. 4443 if (!$dbman->index_exists($table, $index)) { 4444 $dbman->add_index($table, $index); 4445 } 4446 4447 // Main savepoint reached. 4448 upgrade_main_savepoint(true, 2022032200.01); 4449 } 4450 4451 if ($oldversion < 2022032200.02) { 4452 4453 // Define index to be added to question_references. 4454 $table = new xmldb_table('question_set_references'); 4455 $index = new xmldb_index('context-component-area-itemid', XMLDB_INDEX_UNIQUE, 4456 ['usingcontextid', 'component', 'questionarea', 'itemid']); 4457 4458 // Conditionally launch add field id. 4459 if (!$dbman->index_exists($table, $index)) { 4460 $dbman->add_index($table, $index); 4461 } 4462 4463 // Main savepoint reached. 4464 upgrade_main_savepoint(true, 2022032200.02); 4465 } 4466 4467 if ($oldversion < 2022041200.01) { 4468 4469 // The original default admin presets "sensible settings" (those that should be treated as sensitive). 4470 $originalsensiblesettings = 'recaptchapublickey@@none, recaptchaprivatekey@@none, googlemapkey3@@none, ' . 4471 'secretphrase@@url, cronremotepassword@@none, smtpuser@@none, smtppass@none, proxypassword@@none, ' . 4472 'quizpassword@@quiz, allowedip@@none, blockedip@@none, dbpass@@logstore_database, messageinbound_hostpass@@none, ' . 4473 'bind_pw@@auth_cas, pass@@auth_db, bind_pw@@auth_ldap, dbpass@@enrol_database, bind_pw@@enrol_ldap, ' . 4474 'server_password@@search_solr, ssl_keypassword@@search_solr, alternateserver_password@@search_solr, ' . 4475 'alternatessl_keypassword@@search_solr, test_password@@cachestore_redis, password@@mlbackend_python'; 4476 4477 // Check if the current config matches the original default, upgrade to new default if so. 4478 if (get_config('adminpresets', 'sensiblesettings') === $originalsensiblesettings) { 4479 $newsensiblesettings = "{$originalsensiblesettings}, badges_badgesalt@@none, calendar_exportsalt@@none"; 4480 set_config('sensiblesettings', $newsensiblesettings, 'adminpresets'); 4481 } 4482 4483 // Main savepoint reached. 4484 upgrade_main_savepoint(true, 2022041200.01); 4485 } 4486 4487 // Automatically generated Moodle v4.0.0 release upgrade line. 4488 // Put any upgrade step following this. 4489 4490 if ($oldversion < 2022041900.03) { 4491 // Social custom fields could had been created linked to category id = 1. Let's check category 1 exists. 4492 if (!$DB->get_record('user_info_category', ['id' => 1])) { 4493 // Let's check if we have any custom field linked to category id = 1. 4494 $fields = $DB->get_records('user_info_field', ['categoryid' => 1]); 4495 if (!empty($fields)) { 4496 $categoryid = $DB->get_field_sql('SELECT min(id) from {user_info_category}'); 4497 foreach ($fields as $field) { 4498 $field->categoryid = $categoryid; 4499 $DB->update_record('user_info_field', $field); 4500 } 4501 } 4502 } 4503 4504 // Main savepoint reached. 4505 upgrade_main_savepoint(true, 2022041900.03); 4506 } 4507 4508 if ($oldversion < 2022041901.05) { 4509 4510 // Changing precision of field hidden on table grade_categories to (10). 4511 $table = new xmldb_table('grade_categories'); 4512 $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'timemodified'); 4513 4514 // Launch change of precision for field hidden. 4515 $dbman->change_field_precision($table, $field); 4516 4517 // Changing precision of field hidden on table grade_categories_history to (10). 4518 $table = new xmldb_table('grade_categories_history'); 4519 $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'aggregatesubcats'); 4520 4521 // Launch change of precision for field hidden. 4522 $dbman->change_field_precision($table, $field); 4523 4524 // Main savepoint reached. 4525 upgrade_main_savepoint(true, 2022041901.05); 4526 } 4527 4528 if ($oldversion < 2022041901.07) { 4529 // Iterate over custom user menu items configuration, removing pix icon references. 4530 $customusermenuitems = str_replace(["\r\n", "\r"], "\n", $CFG->customusermenuitems); 4531 4532 $lines = preg_split('/\n/', $customusermenuitems, -1, PREG_SPLIT_NO_EMPTY); 4533 $lines = array_map(static function(string $line): string { 4534 // Previous format was "<langstring>|<url>[|<pixicon>]" - pix icon is no longer supported. 4535 $lineparts = explode('|', trim($line), 3); 4536 // Return first two parts of line. 4537 return implode('|', array_slice($lineparts, 0, 2)); 4538 }, $lines); 4539 4540 set_config('customusermenuitems', implode("\n", $lines)); 4541 4542 upgrade_main_savepoint(true, 2022041901.07); 4543 } 4544 4545 if ($oldversion < 2022041904.03) { 4546 4547 // Remove any orphaned tag instance records (pointing to non-existing context). 4548 $DB->delete_records_select('tag_instance', 'NOT EXISTS ( 4549 SELECT ctx.id FROM {context} ctx WHERE ctx.id = {tag_instance}.contextid 4550 )'); 4551 4552 // Main savepoint reached. 4553 upgrade_main_savepoint(true, 2022041904.03); 4554 } 4555 4556 if ($oldversion < 2022041904.14) { 4557 $table = new xmldb_table('h5p'); 4558 $indexpathnamehash = new xmldb_index('pathnamehash_idx', XMLDB_INDEX_NOTUNIQUE, ['pathnamehash']); 4559 4560 if (!$dbman->index_exists($table, $indexpathnamehash)) { 4561 $dbman->add_index($table, $indexpathnamehash); 4562 } 4563 // Main savepoint reached. 4564 upgrade_main_savepoint(true, 2022041904.14); 4565 } 4566 4567 if ($oldversion < 2022041905.07) { 4568 4569 // Remove any orphaned role assignment records (pointing to non-existing roles). 4570 $DB->delete_records_select('role_assignments', 'NOT EXISTS ( 4571 SELECT r.id FROM {role} r WHERE r.id = {role_assignments}.roleid 4572 )'); 4573 4574 // Main savepoint reached. 4575 upgrade_main_savepoint(true, 2022041905.07); 4576 } 4577 4578 if ($oldversion < 2022041908.02) { 4579 4580 // Remove any orphaned role assignment records (pointing to non-existing roles). 4581 $DB->set_field('task_scheduled', 'disabled', 1, ['classname' => '\core\task\question_stats_cleanup_task']); 4582 4583 // Main savepoint reached. 4584 upgrade_main_savepoint(true, 2022041908.02); 4585 } 4586 4587 return true; 4588 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body