Differences Between: [Versions 310 and 311] [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
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 < 2020081400.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, 2020081400.01); 1935 } 1936 1937 if ($oldversion < 2020081400.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, 2020081400.02); 1950 } 1951 1952 if ($oldversion < 2020082200.01) { 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, 2020082200.01); 1990 } 1991 1992 if ($oldversion < 2020082200.02) { 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, 2020082200.02); 2036 } 2037 2038 if ($oldversion < 2020082200.03) { 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, 2020082200.03); 2059 } 2060 2061 if ($oldversion < 2020091000.02) { 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, 2020091000.02); 2069 } 2070 2071 if ($oldversion < 2020091800.01) { 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, 2020091800.01); 2083 } 2084 2085 if ($oldversion < 2020100200.01) { 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, 2020100200.01); 2113 } 2114 2115 if ($oldversion < 2020100700.00) { 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, 2020100700.00); 2137 } 2138 2139 if ($oldversion < 2020101300.01) { 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, 2020101300.01); 2158 } 2159 2160 if ($oldversion < 2020101600.01) { 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, 2020101600.01); 2170 } 2171 2172 if ($oldversion < 2020101600.02) { 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, 2020101600.02); 2192 } 2193 2194 if ($oldversion < 2020102100.01) { 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, 2020102100.01); 2228 } 2229 2230 if ($oldversion < 2020102100.02) { 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, 2020102100.02); 2239 } 2240 2241 if ($oldversion < 2020102300.01) { 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, 2020102300.01); 2252 } 2253 2254 if ($oldversion < 2020102300.02) { 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, 2020102300.02); 2293 } 2294 2295 if ($oldversion < 2020102700.04) { 2296 2297 // Define table payment_accounts to be created. 2298 $table = new xmldb_table('payment_accounts'); 2299 2300 // Adding fields to table payment_accounts. 2301 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2302 $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null); 2303 $table->add_field('idnumber', XMLDB_TYPE_CHAR, '100', null, null, null, null); 2304 $table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2305 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 2306 $table->add_field('archived', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0'); 2307 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 2308 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, null, null, null); 2309 2310 // Adding keys to table payment_accounts. 2311 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 2312 2313 // Conditionally launch create table for payment_accounts. 2314 if (!$dbman->table_exists($table)) { 2315 $dbman->create_table($table); 2316 } 2317 2318 // Define table payment_gateways to be created. 2319 $table = new xmldb_table('payment_gateways'); 2320 2321 // Adding fields to table payment_gateways. 2322 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2323 $table->add_field('accountid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2324 $table->add_field('gateway', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 2325 $table->add_field('enabled', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1'); 2326 $table->add_field('config', XMLDB_TYPE_TEXT, null, null, null, null, null); 2327 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2328 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2329 2330 // Adding keys to table payment_gateways. 2331 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 2332 $table->add_key('accountid', XMLDB_KEY_FOREIGN, ['accountid'], 'payment_accounts', ['id']); 2333 2334 // Conditionally launch create table for payment_gateways. 2335 if (!$dbman->table_exists($table)) { 2336 $dbman->create_table($table); 2337 } 2338 2339 // Define table payments to be created. 2340 $table = new xmldb_table('payments'); 2341 2342 // Adding fields to table payments. 2343 $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null); 2344 $table->add_field('component', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 2345 $table->add_field('paymentarea', XMLDB_TYPE_CHAR, '50', null, XMLDB_NOTNULL, null, null); 2346 $table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2347 $table->add_field('userid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2348 $table->add_field('amount', XMLDB_TYPE_CHAR, '20', null, XMLDB_NOTNULL, null, null); 2349 $table->add_field('currency', XMLDB_TYPE_CHAR, '3', null, XMLDB_NOTNULL, null, null); 2350 $table->add_field('accountid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null); 2351 $table->add_field('gateway', XMLDB_TYPE_CHAR, '100', null, XMLDB_NOTNULL, null, null); 2352 $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2353 $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0'); 2354 2355 // Adding keys to table payments. 2356 $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']); 2357 $table->add_key('userid', XMLDB_KEY_FOREIGN, ['userid'], 'user', ['id']); 2358 $table->add_key('accountid', XMLDB_KEY_FOREIGN, ['accountid'], 'payment_accounts', ['id']); 2359 2360 // Adding indexes to table payments. 2361 $table->add_index('gateway', XMLDB_INDEX_NOTUNIQUE, ['gateway']); 2362 $table->add_index('component-paymentarea-itemid', XMLDB_INDEX_NOTUNIQUE, ['component', 'paymentarea', 'itemid']); 2363 2364 // Conditionally launch create table for payments. 2365 if (!$dbman->table_exists($table)) { 2366 $dbman->create_table($table); 2367 } 2368 2369 // Main savepoint reached. 2370 upgrade_main_savepoint(true, 2020102700.04); 2371 } 2372 2373 // Automatically generated Moodle v3.10.0 release upgrade line. 2374 // Put any upgrade step following this. 2375 2376 if ($oldversion < 2020111500.01) { 2377 // Get all lessons that are set with a completion criteria of 'requires grade' but with no grade type set. 2378 $sql = "SELECT cm.id 2379 FROM {course_modules} cm 2380 JOIN {lesson} l ON l.id = cm.instance 2381 JOIN {modules} m ON m.id = cm.module 2382 WHERE m.name = :name AND cm.completiongradeitemnumber IS NOT NULL AND l.grade = :grade"; 2383 2384 do { 2385 if ($invalidconfigrations = $DB->get_records_sql($sql, ['name' => 'lesson', 'grade' => 0], 0, 1000)) { 2386 list($insql, $inparams) = $DB->get_in_or_equal(array_keys($invalidconfigrations), SQL_PARAMS_NAMED); 2387 $DB->set_field_select('course_modules', 'completiongradeitemnumber', null, "id $insql", $inparams); 2388 } 2389 } while ($invalidconfigrations); 2390 2391 upgrade_main_savepoint(true, 2020111500.01); 2392 } 2393 2394 if ($oldversion < 2021013100.00) { 2395 $DB->delete_records_select('event', "eventtype = 'category' AND categoryid = 0 AND userid <> 0"); 2396 2397 upgrade_main_savepoint(true, 2021013100.00); 2398 } 2399 2400 if ($oldversion < 2021021100.01) { 2401 // Define field visibility to be added to contentbank_content. 2402 $table = new xmldb_table('contentbank_content'); 2403 $field = new xmldb_field('visibility', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'contextid'); 2404 2405 // Conditionally launch add field visibility. 2406 if (!$dbman->field_exists($table, $field)) { 2407 $dbman->add_field($table, $field); 2408 } 2409 2410 // Main savepoint reached. 2411 upgrade_main_savepoint(true, 2021021100.01); 2412 } 2413 2414 if ($oldversion < 2021021600.00) { 2415 2416 // We are going to remove the field 'hidepicture' from the groups 2417 // so we need to remove the pictures from those groups. But we prevent 2418 // the execution twice because this could be executed again when upgrading 2419 // to different versions. 2420 if ($dbman->field_exists('groups', 'hidepicture')) { 2421 2422 $sql = "SELECT g.id, g.courseid, ctx.id AS contextid 2423 FROM {groups} g 2424 JOIN {context} ctx 2425 ON ctx.instanceid = g.courseid 2426 AND ctx.contextlevel = :contextlevel 2427 WHERE g.hidepicture = 1"; 2428 2429 // Selecting all the groups that have hide picture enabled, and organising them by context. 2430 $groupctx = []; 2431 $records = $DB->get_recordset_sql($sql, ['contextlevel' => CONTEXT_COURSE]); 2432 foreach ($records as $record) { 2433 if (!isset($groupctx[$record->contextid])) { 2434 $groupctx[$record->contextid] = []; 2435 } 2436 $groupctx[$record->contextid][] = $record->id; 2437 } 2438 $records->close(); 2439 2440 // Deleting the group files. 2441 $fs = get_file_storage(); 2442 foreach ($groupctx as $contextid => $groupids) { 2443 list($in, $inparams) = $DB->get_in_or_equal($groupids, SQL_PARAMS_NAMED); 2444 $fs->delete_area_files_select($contextid, 'group', 'icon', $in, $inparams); 2445 } 2446 2447 // Updating the database to remove picture from all those groups. 2448 $sql = "UPDATE {groups} SET picture = :pic WHERE hidepicture = :hide"; 2449 $DB->execute($sql, ['pic' => 0, 'hide' => 1]); 2450 } 2451 2452 // Define field hidepicture to be dropped from groups. 2453 $table = new xmldb_table('groups'); 2454 $field = new xmldb_field('hidepicture'); 2455 2456 // Conditionally launch drop field hidepicture. 2457 if ($dbman->field_exists($table, $field)) { 2458 $dbman->drop_field($table, $field); 2459 } 2460 2461 // Main savepoint reached. 2462 upgrade_main_savepoint(true, 2021021600.00); 2463 } 2464 2465 if ($oldversion < 2021022600.01) { 2466 // Get all the external backpacks and update the sortorder column, to avoid repeated/wrong values. As sortorder was not 2467 // used since now, the id column will be the criteria to follow for re-ordering them with a valid value. 2468 $i = 1; 2469 $records = $DB->get_records('badge_external_backpack', null, 'id ASC'); 2470 foreach ($records as $record) { 2471 $record->sortorder = $i++; 2472 $DB->update_record('badge_external_backpack', $record); 2473 } 2474 2475 upgrade_main_savepoint(true, 2021022600.01); 2476 } 2477 2478 if ($oldversion < 2021030500.01) { 2479 // The $CFG->badges_site_backpack setting has been removed because it's not required anymore. From now, the default backpack 2480 // will be the one with lower sortorder value. 2481 unset_config('badges_site_backpack'); 2482 2483 upgrade_main_savepoint(true, 2021030500.01); 2484 } 2485 2486 if ($oldversion < 2021031200.01) { 2487 2488 // Define field type to be added to oauth2_issuer. 2489 $table = new xmldb_table('oauth2_issuer'); 2490 $field = new xmldb_field('servicetype', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'requireconfirmation'); 2491 2492 // Conditionally launch add field type. 2493 if (!$dbman->field_exists($table, $field)) { 2494 $dbman->add_field($table, $field); 2495 } 2496 2497 // Set existing values to the proper servicetype value. 2498 // It's not critical if the servicetype column doesn't contain the proper value for Google, Microsoft, Facebook or 2499 // Nextcloud services because, for now, this value is used for services using different discovery method. 2500 // However, let's try to upgrade it using the default value for the baseurl or image. If any of these default values 2501 // have been changed, the servicetype column will remain NULL. 2502 $recordset = $DB->get_recordset('oauth2_issuer'); 2503 foreach ($recordset as $record) { 2504 if ($record->baseurl == 'https://accounts.google.com/') { 2505 $record->servicetype = 'google'; 2506 $DB->update_record('oauth2_issuer', $record); 2507 } else if ($record->image == 'https://www.microsoft.com/favicon.ico') { 2508 $record->servicetype = 'microsoft'; 2509 $DB->update_record('oauth2_issuer', $record); 2510 } else if ($record->image == 'https://facebookbrand.com/wp-content/uploads/2016/05/flogo_rgb_hex-brc-site-250.png') { 2511 $record->servicetype = 'facebook'; 2512 $DB->update_record('oauth2_issuer', $record); 2513 } else if ($record->image == 'https://nextcloud.com/wp-content/themes/next/assets/img/common/favicon.png?x16328') { 2514 $record->servicetype = 'nextcloud'; 2515 $DB->update_record('oauth2_issuer', $record); 2516 } 2517 } 2518 $recordset->close(); 2519 2520 // Main savepoint reached. 2521 upgrade_main_savepoint(true, 2021031200.01); 2522 } 2523 2524 if ($oldversion < 2021033100.00) { 2525 // Define field 'showactivitydates' to be added to course table. 2526 $table = new xmldb_table('course'); 2527 $field = new xmldb_field('showactivitydates', XMLDB_TYPE_INTEGER, '1', null, 2528 XMLDB_NOTNULL, null, '0', 'originalcourseid'); 2529 2530 if (!$dbman->field_exists($table, $field)) { 2531 $dbman->add_field($table, $field); 2532 } 2533 2534 // Main savepoint reached. 2535 upgrade_main_savepoint(true, 2021033100.00); 2536 } 2537 2538 if ($oldversion < 2021033100.01) { 2539 // Define field 'showcompletionconditions' to be added to course. 2540 $table = new xmldb_table('course'); 2541 $field = new xmldb_field('showcompletionconditions', XMLDB_TYPE_INTEGER, '1', null, 2542 XMLDB_NOTNULL, null, '1', 'completionnotify'); 2543 2544 if (!$dbman->field_exists($table, $field)) { 2545 $dbman->add_field($table, $field); 2546 } 2547 2548 // Main savepoint reached. 2549 upgrade_main_savepoint(true, 2021033100.01); 2550 } 2551 2552 if ($oldversion < 2021041300.01) { 2553 2554 // Define field enabled to be added to h5p_libraries. 2555 $table = new xmldb_table('h5p_libraries'); 2556 $field = new xmldb_field('enabled', XMLDB_TYPE_INTEGER, '1', null, null, null, '1', 'example'); 2557 2558 // Conditionally launch add field enabled. 2559 if (!$dbman->field_exists($table, $field)) { 2560 $dbman->add_field($table, $field); 2561 } 2562 2563 // Main savepoint reached. 2564 upgrade_main_savepoint(true, 2021041300.01); 2565 } 2566 2567 if ($oldversion < 2021042100.00) { 2568 2569 // Define field loginpagename to be added to oauth2_issuer. 2570 $table = new xmldb_table('oauth2_issuer'); 2571 $field = new xmldb_field('loginpagename', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'servicetype'); 2572 2573 // Conditionally launch add field loginpagename. 2574 if (!$dbman->field_exists($table, $field)) { 2575 $dbman->add_field($table, $field); 2576 } 2577 2578 // Main savepoint reached. 2579 upgrade_main_savepoint(true, 2021042100.00); 2580 } 2581 2582 if ($oldversion < 2021042100.01) { 2583 require_once($CFG->dirroot . '/user/profile/field/social/upgradelib.php'); 2584 $table = new xmldb_table('user'); 2585 $tablecolumns = ['icq', 'skype', 'aim', 'yahoo', 'msn', 'url']; 2586 2587 foreach ($tablecolumns as $column) { 2588 $field = new xmldb_field($column); 2589 if ($dbman->field_exists($table, $field)) { 2590 user_profile_social_moveto_profilefield($column); 2591 $dbman->drop_field($table, $field); 2592 } 2593 } 2594 2595 // Update all module availability if it relies on the old user fields. 2596 user_profile_social_update_module_availability(); 2597 2598 // Remove field mapping for oauth2. 2599 $DB->delete_records('oauth2_user_field_mapping', array('internalfield' => 'url')); 2600 2601 // Main savepoint reached. 2602 upgrade_main_savepoint(true, 2021042100.01); 2603 } 2604 2605 if ($oldversion < 2021042100.02) { 2606 require_once($CFG->libdir . '/db/upgradelib.php'); 2607 2608 // Check if this site has executed the problematic upgrade steps. 2609 $needsfixing = upgrade_calendar_site_status(false); 2610 2611 // Only queue the task if this site has been affected by the problematic upgrade step. 2612 if ($needsfixing) { 2613 2614 // Create adhoc task to search and recover orphaned calendar events. 2615 $record = new \stdClass(); 2616 $record->classname = '\core\task\calendar_fix_orphaned_events'; 2617 2618 // Next run time based from nextruntime computation in \core\task\manager::queue_adhoc_task(). 2619 $nextruntime = time() - 1; 2620 $record->nextruntime = $nextruntime; 2621 $DB->insert_record('task_adhoc', $record); 2622 } 2623 2624 // Main savepoint reached. 2625 upgrade_main_savepoint(true, 2021042100.02); 2626 } 2627 2628 if ($oldversion < 2021042400.00) { 2629 // Changing the default of field showcompletionconditions on table course to 0. 2630 $table = new xmldb_table('course'); 2631 $field = new xmldb_field('showcompletionconditions', XMLDB_TYPE_INTEGER, '1', null, null, null, null, 'showactivitydates'); 2632 2633 // Launch change of nullability for field showcompletionconditions. 2634 $dbman->change_field_notnull($table, $field); 2635 2636 // Launch change of default for field showcompletionconditions. 2637 $dbman->change_field_default($table, $field); 2638 2639 // Set showcompletionconditions to null for courses which don't track completion. 2640 $sql = "UPDATE {course} 2641 SET showcompletionconditions = null 2642 WHERE enablecompletion <> 1"; 2643 $DB->execute($sql); 2644 2645 // Main savepoint reached. 2646 upgrade_main_savepoint(true, 2021042400.00); 2647 } 2648 2649 if ($oldversion < 2021043000.01) { 2650 // Remove usemodchooser user preference for every user. 2651 $DB->delete_records('user_preferences', ['name' => 'usemodchooser']); 2652 2653 // Main savepoint reached. 2654 upgrade_main_savepoint(true, 2021043000.01); 2655 } 2656 2657 // Automatically generated Moodle v3.11.0 release upgrade line. 2658 // Put any upgrade step following this. 2659 2660 if ($oldversion < 2021051700.03) { 2661 2662 // Define index name (not unique) to be added to user_preferences. 2663 $table = new xmldb_table('user_preferences'); 2664 $index = new xmldb_index('name', XMLDB_INDEX_NOTUNIQUE, ['name']); 2665 2666 // Conditionally launch add index name. 2667 if (!$dbman->index_exists($table, $index)) { 2668 $dbman->add_index($table, $index); 2669 } 2670 2671 // Main savepoint reached. 2672 upgrade_main_savepoint(true, 2021051700.03); 2673 } 2674 2675 if ($oldversion < 2021051700.05) { 2676 // Update the externalfield to be larger. 2677 $table = new xmldb_table('oauth2_user_field_mapping'); 2678 $field = new xmldb_field('externalfield', XMLDB_TYPE_CHAR, '500', null, XMLDB_NOTNULL, false, null, 'issuerid'); 2679 $dbman->change_field_type($table, $field); 2680 2681 // Main savepoint reached. 2682 upgrade_main_savepoint(true, 2021051700.05); 2683 } 2684 2685 if ($oldversion < 2021051706.12) { 2686 // Social custom fields could had been created linked to category id = 1. Let's check category 1 exists. 2687 if (!$DB->get_record('user_info_category', ['id' => 1])) { 2688 // Let's check if we have any custom field linked to category id = 1. 2689 $fields = $DB->get_records('user_info_field', ['categoryid' => 1]); 2690 if (!empty($fields)) { 2691 $categoryid = $DB->get_field_sql('SELECT min(id) from {user_info_category}'); 2692 foreach ($fields as $field) { 2693 $field->categoryid = $categoryid; 2694 $DB->update_record('user_info_field', $field); 2695 } 2696 } 2697 } 2698 2699 // Main savepoint reached. 2700 upgrade_main_savepoint(true, 2021051706.12); 2701 } 2702 2703 if ($oldversion < 2021051707.05) { 2704 2705 // Changing precision of field hidden on table grade_categories to (10). 2706 $table = new xmldb_table('grade_categories'); 2707 $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'timemodified'); 2708 2709 // Launch change of precision for field hidden. 2710 $dbman->change_field_precision($table, $field); 2711 2712 // Changing precision of field hidden on table grade_categories_history to (10). 2713 $table = new xmldb_table('grade_categories_history'); 2714 $field = new xmldb_field('hidden', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, '0', 'aggregatesubcats'); 2715 2716 // Launch change of precision for field hidden. 2717 $dbman->change_field_precision($table, $field); 2718 2719 // Main savepoint reached. 2720 upgrade_main_savepoint(true, 2021051707.05); 2721 } 2722 2723 if ($oldversion < 2021051710.03) { 2724 2725 // Remove any orphaned tag instance records (pointing to non-existing context). 2726 $DB->delete_records_select('tag_instance', 'NOT EXISTS ( 2727 SELECT ctx.id FROM {context} ctx WHERE ctx.id = {tag_instance}.contextid 2728 )'); 2729 2730 // Main savepoint reached. 2731 upgrade_main_savepoint(true, 2021051710.03); 2732 } 2733 2734 if ($oldversion < 2021051710.14) { 2735 $table = new xmldb_table('h5p'); 2736 $indexpathnamehash = new xmldb_index('pathnamehash_idx', XMLDB_INDEX_NOTUNIQUE, ['pathnamehash']); 2737 2738 if (!$dbman->index_exists($table, $indexpathnamehash)) { 2739 $dbman->add_index($table, $indexpathnamehash); 2740 } 2741 // Main savepoint reached. 2742 upgrade_main_savepoint(true, 2021051710.14); 2743 } 2744 2745 return true; 2746 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body