Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.0.x will end 8 May 2023 (12 months).
  • Bug fixes for security issues in 4.0.x will end 13 November 2023 (18 months).
  • PHP version: minimum PHP 7.3.0 Note: the minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is also supported.

Differences Between: [Versions 310 and 400] [Versions 311 and 400] [Versions 39 and 400] [Versions 400 and 401] [Versions 400 and 402] [Versions 400 and 403]

   1  <?php
   2  // This file is part of Moodle - http://moodle.org/
   3  //
   4  // Moodle is free software: you can redistribute it and/or modify
   5  // it under the terms of the GNU General Public License as published by
   6  // the Free Software Foundation, either version 3 of the License, or
   7  // (at your option) any later version.
   8  //
   9  // Moodle is distributed in the hope that it will be useful,
  10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12  // GNU General Public License for more details.
  13  //
  14  // You should have received a copy of the GNU General Public License
  15  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  16  //
  17  
  18  /**
  19   * This file keeps track of upgrades to the lti enrolment plugin
  20   *
  21   * @package enrol_lti
  22   * @copyright  2016 John Okely <john@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26   defined('MOODLE_INTERNAL') || die;
  27  
  28  /**
  29   * xmldb_lti_upgrade is the function that upgrades
  30   * the lti module database when is needed
  31   *
  32   * This function is automaticly called when version number in
  33   * version.php changes.
  34   *
  35   * @param int $oldversion New old version number.
  36   *
  37   * @return boolean
  38   */
  39  function xmldb_enrol_lti_upgrade($oldversion) {
  40      global $CFG, $OUTPUT, $DB;
  41      $dbman = $DB->get_manager();
  42  
  43      // Automatically generated Moodle v3.6.0 release upgrade line.
  44      // Put any upgrade step following this.
  45  
  46      // Automatically generated Moodle v3.7.0 release upgrade line.
  47      // Put any upgrade step following this.
  48  
  49      // Automatically generated Moodle v3.8.0 release upgrade line.
  50      // Put any upgrade step following this.
  51  
  52      // Automatically generated Moodle v3.9.0 release upgrade line.
  53      // Put any upgrade step following this.
  54  
  55      if ($oldversion < 2021052501) {
  56          // LTI 1.3: Set a private key for this site (which is acting as a tool in LTI 1.3).
  57          require_once($CFG->dirroot . '/enrol/lti/upgradelib.php');
  58  
  59          $warning = enrol_lti_verify_private_key();
  60          if (!empty($warning)) {
  61              echo $OUTPUT->notification($warning, 'notifyproblem');
  62          }
  63  
  64          // Lti savepoint reached.
  65          upgrade_plugin_savepoint(true, 2021052501, 'enrol', 'lti');
  66      }
  67  
  68      if ($oldversion < 2021052502) {
  69          // Define table enrol_lti_app_registration to be created.
  70          $table = new xmldb_table('enrol_lti_app_registration');
  71  
  72          // Adding fields to table enrol_lti_app_registration.
  73          $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
  74          $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
  75          $table->add_field('platformid', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
  76          $table->add_field('clientid', XMLDB_TYPE_CHAR, '1333', null, XMLDB_NOTNULL, null, null);
  77          $table->add_field('platformclienthash', XMLDB_TYPE_CHAR, '64', null, XMLDB_NOTNULL, null, null);
  78          $table->add_field('authenticationrequesturl', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
  79          $table->add_field('jwksurl', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
  80          $table->add_field('accesstokenurl', XMLDB_TYPE_TEXT, null, null, XMLDB_NOTNULL, null, null);
  81          $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
  82          $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
  83  
  84          // Adding keys to table enrol_lti_app_registration.
  85          $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
  86  
  87          // Add unique index on platformclienthash.
  88          $table->add_index('platformclienthash', XMLDB_INDEX_UNIQUE, ['platformclienthash']);
  89  
  90          // Conditionally launch create table for enrol_lti_app_registration.
  91          if (!$dbman->table_exists($table)) {
  92              $dbman->create_table($table);
  93          }
  94  
  95          // Lti savepoint reached.
  96          upgrade_plugin_savepoint(true, 2021052502, 'enrol', 'lti');
  97      }
  98  
  99      if ($oldversion < 2021052503) {
 100          // Add a new column 'ltiversion' to the enrol_lti_tools table.
 101          $table = new xmldb_table('enrol_lti_tools');
 102  
 103          // Define field ltiversion to be added to enrol_lti_tools.
 104          $field = new xmldb_field('ltiversion', XMLDB_TYPE_CHAR, 15, null, XMLDB_NOTNULL, null, "LTI-1p3", 'contextid');
 105  
 106          // Conditionally launch add field ltiversion, setting it to the legacy value for all published content.
 107          if (!$dbman->field_exists($table, $field)) {
 108              $dbman->add_field($table, $field);
 109              $DB->set_field('enrol_lti_tools', 'ltiversion', 'LTI-1p0/LTI-2p0');
 110          }
 111  
 112          // Define field uuid to be added to enrol_lti_tools.
 113          $field = new xmldb_field('uuid', XMLDB_TYPE_CHAR, 36, null, null, null, null, 'ltiversion');
 114  
 115          // Conditionally launch add field uuid, setting it to null for existing rows.
 116          if (!$dbman->field_exists($table, $field)) {
 117              $dbman->add_field($table, $field);
 118              $key = new xmldb_key('uuid', XMLDB_KEY_UNIQUE, ['uuid']);
 119              $dbman->add_key($table, $key);
 120          }
 121  
 122          // Lti savepoint reached.
 123          upgrade_plugin_savepoint(true, 2021052503, 'enrol', 'lti');
 124      }
 125  
 126      if ($oldversion < 2021052504) {
 127          // Define table enrol_lti_deployment to be created.
 128          $table = new xmldb_table('enrol_lti_deployment');
 129  
 130          // Adding fields to table enrol_lti_deployment.
 131          $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
 132          $table->add_field('name', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
 133          $table->add_field('deploymentid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
 134          $table->add_field('platformid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 135          $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 136          $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 137  
 138          // Adding keys to table enrol_lti_deployment.
 139          $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
 140          $table->add_key('platformid', XMLDB_KEY_FOREIGN, ['platformid'], 'enrol_lti_app_registration', ['id']);
 141  
 142          // Add unique index on platformid (issuer), deploymentid.
 143          $table->add_index('platformid-deploymentid', XMLDB_INDEX_UNIQUE, ['platformid', 'deploymentid']);
 144  
 145          // Conditionally launch create table for enrol_lti_deployment.
 146          if (!$dbman->table_exists($table)) {
 147              $dbman->create_table($table);
 148          }
 149  
 150          // Lti savepoint reached.
 151          upgrade_plugin_savepoint(true, 2021052504, 'enrol', 'lti');
 152      }
 153  
 154      if ($oldversion < 2021052505) {
 155          // Add a new column 'ltideploymentid' to the enrol_lti_users table.
 156          $table = new xmldb_table('enrol_lti_users');
 157  
 158          // Define field ltideploymentid to be added to enrol_lti_users.
 159          $field = new xmldb_field('ltideploymentid', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'sourceid');
 160  
 161          // Conditionally launch add field deploymentid.
 162          if (!$dbman->field_exists($table, $field)) {
 163              $dbman->add_field($table, $field);
 164          }
 165  
 166          // Launch add key ltideploymentid.
 167          $key = new xmldb_key('ltideploymentid', XMLDB_KEY_FOREIGN, ['ltideploymentid'], 'enrol_lti_deployment', ['id']);
 168          $dbman->add_key($table, $key);
 169  
 170          // Lti savepoint reached.
 171          upgrade_plugin_savepoint(true, 2021052505, 'enrol', 'lti');
 172      }
 173  
 174      if ($oldversion < 2021052506) {
 175          // Define table enrol_lti_resource_link to be created.
 176          $table = new xmldb_table('enrol_lti_resource_link');
 177  
 178          // Adding fields to table enrol_lti_resource_link.
 179          $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
 180          $table->add_field('resourcelinkid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
 181          $table->add_field('resourceid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 182          $table->add_field('ltideploymentid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 183          $table->add_field('lticontextid', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
 184          $table->add_field('lineitemsservice', XMLDB_TYPE_CHAR, '1333', null, null, null, null);
 185          $table->add_field('lineitemservice', XMLDB_TYPE_CHAR, '1333', null, null, null, null);
 186          $table->add_field('lineitemscope', XMLDB_TYPE_CHAR, '255', null, null, null, null);
 187          $table->add_field('resultscope', XMLDB_TYPE_CHAR, '255', null, null, null, null);
 188          $table->add_field('scorescope', XMLDB_TYPE_CHAR, '255', null, null, null, null);
 189          $table->add_field('contextmembershipsurl', XMLDB_TYPE_CHAR, '1333', null, null, null, null);
 190          $table->add_field('nrpsserviceversions', XMLDB_TYPE_CHAR, '255', null, null, null, null);
 191          $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 192          $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 193  
 194          // Adding keys to table enrol_lti_resource_link.
 195          $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
 196          $table->add_key('ltideploymentid', XMLDB_KEY_FOREIGN, ['ltideploymentid'], 'enrol_lti_deployment', ['id']);
 197          $table->add_key('lticontextid', XMLDB_KEY_FOREIGN, ['lticontextid'], 'enrol_lti_context', ['id']);
 198  
 199          // Add unique index on resourcelinkid, ltideploymentid.
 200          $table->add_index('resourcelinkdid-ltideploymentid', XMLDB_INDEX_UNIQUE, ['resourcelinkid', 'ltideploymentid']);
 201  
 202          // Conditionally launch create table for enrol_lti_resource_link.
 203          if (!$dbman->table_exists($table)) {
 204              $dbman->create_table($table);
 205          }
 206  
 207          // Lti savepoint reached.
 208          upgrade_plugin_savepoint(true, 2021052506, 'enrol', 'lti');
 209      }
 210  
 211      if ($oldversion < 2021052507) {
 212          // Define table enrol_lti_context to be created.
 213          $table = new xmldb_table('enrol_lti_context');
 214  
 215          // Adding fields to table enrol_lti_context.
 216          $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
 217          $table->add_field('contextid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null);
 218          $table->add_field('ltideploymentid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 219          $table->add_field('type', XMLDB_TYPE_TEXT, null, null, null, null, null);
 220          $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 221          $table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 222  
 223          // Adding keys to table enrol_lti_context.
 224          $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
 225          $table->add_key('ltideploymentid', XMLDB_KEY_FOREIGN, ['ltideploymentid'], 'enrol_lti_deployment', ['id']);
 226  
 227          // Add unique index on ltideploymentid, contextid.
 228          $table->add_index('ltideploymentid-contextid', XMLDB_INDEX_UNIQUE, ['ltideploymentid', 'contextid']);
 229  
 230          // Conditionally launch create table for enrol_lti_context.
 231          if (!$dbman->table_exists($table)) {
 232              $dbman->create_table($table);
 233          }
 234  
 235          upgrade_plugin_savepoint(true, 2021052507, 'enrol', 'lti');
 236      }
 237  
 238      if ($oldversion < 2021052508) {
 239          // Define table enrol_lti_user_resource_link to be created.
 240          $table = new xmldb_table('enrol_lti_user_resource_link');
 241  
 242          // Adding fields to table enrol_lti_user_resource_link.
 243          $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
 244          $table->add_field('ltiuserid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 245          $table->add_field('resourcelinkid', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 246  
 247          // Adding keys to table enrol_lti_user_resource_link.
 248          $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
 249          $table->add_key('ltiuserid', XMLDB_KEY_FOREIGN, ['ltiuserid'], 'enrol_lti_users', ['id']);
 250          $table->add_key('resourcelinkid', XMLDB_KEY_FOREIGN, ['resourcelinkid'], 'enrol_lti_resource_link', ['id']);
 251  
 252          // Add unique index on userid, resourcelinkid.
 253          $table->add_index('ltiuserid-resourcelinkid', XMLDB_INDEX_UNIQUE, ['ltiuserid', 'resourcelinkid']);
 254  
 255          // Conditionally launch create table for enrol_lti_user_resource_link.
 256          if (!$dbman->table_exists($table)) {
 257              $dbman->create_table($table);
 258          }
 259          upgrade_plugin_savepoint(true, 2021052508, 'enrol', 'lti');
 260      }
 261  
 262      if ($oldversion < 2021052512) {
 263          // Define field legacyconsumerkey to be added to enrol_lti_deployment.
 264          $table = new xmldb_table('enrol_lti_deployment');
 265          $field = new xmldb_field('legacyconsumerkey', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'platformid');
 266  
 267          // Conditionally launch add field legacyconsumerkey.
 268          if (!$dbman->field_exists($table, $field)) {
 269              $dbman->add_field($table, $field);
 270          }
 271  
 272          upgrade_plugin_savepoint(true, 2021052512, 'enrol', 'lti');
 273      }
 274  
 275      if ($oldversion < 2021052513) {
 276          // Define table enrol_lti_reg_token to be created.
 277          $table = new xmldb_table('enrol_lti_reg_token');
 278  
 279          // Adding fields to table enrol_lti_reg_token.
 280          $table->add_field('id', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
 281          $table->add_field('token', XMLDB_TYPE_CHAR, '60', null, XMLDB_NOTNULL, null, null);
 282          $table->add_field('expirytime', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 283          $table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', null, XMLDB_NOTNULL, null, null);
 284  
 285          // Adding keys to table enrol_lti_reg_token.
 286          $table->add_key('primary', XMLDB_KEY_PRIMARY, ['id']);
 287  
 288          // Conditionally launch create table for enrol_lti_reg_token.
 289          if (!$dbman->table_exists($table)) {
 290              $dbman->create_table($table);
 291          }
 292  
 293          upgrade_plugin_savepoint(true, 2021052513, 'enrol', 'lti');
 294      }
 295  
 296      if ($oldversion < 2021052514) {
 297          // Add a new column 'provisioningmodelearner' to the enrol_lti_tools table.
 298          $table = new xmldb_table('enrol_lti_tools');
 299  
 300          // Define field provisioningmodelearner to be added to enrol_lti_tools.
 301          $field = new xmldb_field('provisioningmodelearner', XMLDB_TYPE_INTEGER, 2, null, null, null, null, 'uuid');
 302  
 303          // Conditionally launch add field provisioningmodelearner.
 304          if (!$dbman->field_exists($table, $field)) {
 305              $dbman->add_field($table, $field);
 306          }
 307  
 308          // Define field provisioningmodeinstructor to be added to enrol_lti_tools.
 309          $field = new xmldb_field('provisioningmodeinstructor', XMLDB_TYPE_INTEGER, 2, null, null, null, null,
 310              'provisioningmodelearner');
 311  
 312          // Conditionally launch add field provisioningmodeinstructor.
 313          if (!$dbman->field_exists($table, $field)) {
 314              $dbman->add_field($table, $field);
 315          }
 316  
 317          // Lti savepoint reached.
 318          upgrade_plugin_savepoint(true, 2021052514, 'enrol', 'lti');
 319      }
 320  
 321      if ($oldversion < 2022031400) {
 322          // Changing the default of field platformid on table enrol_lti_app_registration to null.
 323          $table = new xmldb_table('enrol_lti_app_registration');
 324          $field = new xmldb_field('platformid', XMLDB_TYPE_TEXT, null, null, null, null, null, 'name');
 325  
 326          // Launch change of nullability for field platformid.
 327          $dbman->change_field_notnull($table, $field);
 328  
 329          // Changing the default of field clientid on table enrol_lti_app_registration to null.
 330          $field = new xmldb_field('clientid', XMLDB_TYPE_CHAR, '1333', null, null, null, null, 'platformid');
 331  
 332          // Launch change of nullability for field clientid.
 333          $dbman->change_field_notnull($table, $field);
 334  
 335          // Drop the platformclienthash index, so the field can be modified.
 336          $index = new xmldb_index('platformclienthash', XMLDB_INDEX_UNIQUE, ['platformclienthash']);
 337  
 338          // Conditionally launch drop index platformclienthash.
 339          if ($dbman->index_exists($table, $index)) {
 340              $dbman->drop_index($table, $index);
 341          }
 342  
 343          // Changing the default of field platformclienthash on table enrol_lti_app_registration to null.
 344          $field = new xmldb_field('platformclienthash', XMLDB_TYPE_CHAR, '64', null, null, null, null, 'clientid');
 345  
 346          // Launch change of nullability for field platformclienthash.
 347          $dbman->change_field_notnull($table, $field);
 348  
 349          // Recreate the platformclienthash index.
 350          if (!$dbman->index_exists($table, $index)) {
 351              $dbman->add_index($table, $index);
 352          }
 353  
 354          // Changing the default of field authenticationrequesturl on table enrol_lti_app_registration to null.
 355          $field = new xmldb_field('authenticationrequesturl', XMLDB_TYPE_TEXT, null, null, null, null, null, 'platformclienthash');
 356  
 357          // Launch change of nullability for field authenticationrequesturl.
 358          $dbman->change_field_notnull($table, $field);
 359  
 360          // Changing the default of field jwksurl on table enrol_lti_app_registration to null.
 361          $field = new xmldb_field('jwksurl', XMLDB_TYPE_TEXT, null, null, null, null, null, 'authenticationrequesturl');
 362  
 363          // Launch change of nullability for field jwksurl.
 364          $dbman->change_field_notnull($table, $field);
 365  
 366          // Changing the default of field accesstokenurl on table enrol_lti_app_registration to null.
 367          $field = new xmldb_field('accesstokenurl', XMLDB_TYPE_TEXT, null, null, null, null, null, 'jwksurl');
 368  
 369          // Launch change of nullability for field accesstokenurl.
 370          $dbman->change_field_notnull($table, $field);
 371  
 372          // Lti savepoint reached.
 373          upgrade_plugin_savepoint(true, 2022031400, 'enrol', 'lti');
 374      }
 375  
 376      if ($oldversion < 2022031401) {
 377          // Define field uniqueid to be added to enrol_lti_app_registration (defined as null so it can be set for existing rows).
 378          $table = new xmldb_table('enrol_lti_app_registration');
 379          $field = new xmldb_field('uniqueid', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'accesstokenurl');
 380  
 381          // Conditionally launch add field uniqueid.
 382          if (!$dbman->field_exists($table, $field)) {
 383              $dbman->add_field($table, $field);
 384  
 385              // Set existing values to use a suitable unique id.
 386              $recordset = $DB->get_recordset('enrol_lti_app_registration');
 387              foreach ($recordset as $record) {
 388                  // Create a unique id for the registration. This will be used by:
 389                  // a) The initiate_login endpoint (enrol/lti/login.php), as a stand in for client_id, when that's not provided.
 390                  // b) The dynamic registration endpoint, where it'll be used to identify the incomplete registration to update
 391                  // with the platform details.
 392                  do {
 393                      $bytes = random_bytes(30);
 394                      $record->uniqueid = bin2hex($bytes);
 395                  } while ($DB->record_exists('enrol_lti_app_registration', ['uniqueid' => $record->uniqueid]));
 396  
 397                  $DB->update_record('enrol_lti_app_registration', $record);
 398              }
 399              $recordset->close();
 400  
 401              // Now make the field notnull.
 402              $field = new xmldb_field('uniqueid', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'accesstokenurl');
 403              $dbman->change_field_notnull($table, $field);
 404          }
 405  
 406          // Launch add unique key uniqueid.
 407          $key = new xmldb_key('uniqueid', XMLDB_KEY_UNIQUE, ['uniqueid']);
 408          $dbman->add_key($table, $key);
 409  
 410          // Define field status to be added to enrol_lti_app_registration with a default value of 1 (to set existing rows).
 411          $field = new xmldb_field('status', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'uniqueid');
 412  
 413          // Conditionally launch add field status.
 414          if (!$dbman->field_exists($table, $field)) {
 415              $dbman->add_field($table, $field);
 416  
 417              // Now change the default value to '0'.
 418              $field = new xmldb_field('status', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'uniqueid');
 419              $dbman->change_field_default($table, $field);
 420          }
 421  
 422          // Define field platformuniqueidhash to be added to enrol_lti_app_registration.
 423          $field = new xmldb_field('platformuniqueidhash', XMLDB_TYPE_CHAR, '64', null, null, null, null, 'status');
 424          if (!$dbman->field_exists($table, $field)) {
 425              $dbman->add_field($table, $field);
 426  
 427              $recordset = $DB->get_recordset('enrol_lti_app_registration');
 428              foreach ($recordset as $record) {
 429                  $record->platformuniqueidhash = hash('sha256', $record->platformid . ':' . $record->uniqueid);
 430                  $DB->update_record('enrol_lti_app_registration', $record);
 431              }
 432              $recordset->close();
 433          }
 434  
 435          // Add index platformuniqueidhash to enrol_lti_app_registration.
 436          $index = new xmldb_index('platformuniqueidhash', XMLDB_INDEX_UNIQUE, ['platformuniqueidhash']);
 437  
 438          if (!$dbman->index_exists($table, $index)) {
 439              $dbman->add_index($table, $index);
 440          }
 441  
 442          // Lti savepoint reached.
 443          upgrade_plugin_savepoint(true, 2022031401, 'enrol', 'lti');
 444      }
 445  
 446      if ($oldversion < 2022031402) {
 447          // Define table enrol_lti_reg_token to be dropped.
 448          $table = new xmldb_table('enrol_lti_reg_token');
 449  
 450          // Conditionally launch drop table for enrol_lti_reg_token.
 451          if ($dbman->table_exists($table)) {
 452              $dbman->drop_table($table);
 453          }
 454  
 455          // Lti savepoint reached.
 456          upgrade_plugin_savepoint(true, 2022031402, 'enrol', 'lti');
 457      }
 458  
 459      // Automatically generated Moodle v4.0.0 release upgrade line.
 460      // Put any upgrade step following this.
 461  
 462      if ($oldversion < 2022041901) {
 463          // Disable all orphaned enrolment method instances.
 464          $sql = "id IN (SELECT t.enrolid
 465                           FROM {enrol_lti_tools} t
 466                      LEFT JOIN {context} c ON (t.contextid = c.id)
 467                          WHERE c.id IS NULL)";
 468          $DB->set_field_select('enrol', 'status', 1, $sql);
 469  
 470          // Lti savepoint reached.
 471          upgrade_plugin_savepoint(true, 2022041901, 'enrol', 'lti');
 472      }
 473  
 474      if ($oldversion < 2022041902) {
 475          // Update lti user information for LTI 2.0 users having the wrong consumer secret recorded.
 476          // This applies to any LTI 2.0 user who has launched the tool (i.e. has lastaccess) and fixes a non-functional grade sync
 477          // for LTI 2.0 consumers.
 478          $sql = "SELECT lu.id, lc.secret
 479                    FROM {enrol_lti_users} lu
 480                    JOIN {enrol_lti_lti2_consumer} lc
 481                      ON (" . $DB->sql_compare_text('lu.consumerkey', 255) . " = lc.consumerkey256)
 482                   WHERE lc.ltiversion = :ltiversion
 483                     AND " . $DB->sql_compare_text('lu.consumersecret') . " != lc.secret
 484                     AND lu.lastaccess IS NOT NULL";
 485          $affectedltiusersrs = $DB->get_recordset_sql($sql, ['ltiversion' => 'LTI-2p0']);
 486          foreach ($affectedltiusersrs as $ltiuser) {
 487              $DB->set_field('enrol_lti_users', 'consumersecret', $ltiuser->secret, ['id' => $ltiuser->id]);
 488          }
 489          $affectedltiusersrs->close();
 490  
 491          // Lti savepoint reached.
 492          upgrade_plugin_savepoint(true, 2022041902, 'enrol', 'lti');
 493      }
 494  
 495      if ($oldversion < 2022041903) {
 496          // Update lti user information for any users missing a consumer secret.
 497          // This applies to any user who has launched the tool (i.e. has lastaccess) but who doesn't have a secret recorded.
 498          // This fixes a bug where enrol_lti_users records are created first during a member sync, and are missing the secret,
 499          // even despite having launched the tool subsequently.
 500          $sql = "SELECT lu.id, lc.secret
 501                    FROM {enrol_lti_users} lu
 502                    JOIN {enrol_lti_lti2_consumer} lc
 503                      ON (" . $DB->sql_compare_text('lu.consumerkey', 255) . " = lc.consumerkey256)
 504                   WHERE lu.consumersecret IS NULL
 505                     AND lu.lastaccess IS NOT NULL";
 506          $affectedltiusersrs = $DB->get_recordset_sql($sql);
 507          foreach ($affectedltiusersrs as $ltiuser) {
 508              $DB->set_field('enrol_lti_users', 'consumersecret', $ltiuser->secret, ['id' => $ltiuser->id]);
 509          }
 510          $affectedltiusersrs->close();
 511  
 512          // Lti savepoint reached.
 513          upgrade_plugin_savepoint(true, 2022041903, 'enrol', 'lti');
 514      }
 515  
 516      return true;
 517  }