diff --git a/enrol/lti/db/upgrade.php b/enrol/lti/db/upgrade.php index 1af30fc505f..e67e5329aeb 100644 --- a/enrol/lti/db/upgrade.php +++ b/enrol/lti/db/upgrade.php @@ -37,7 +37,7 @@ * @return boolean */ function xmldb_enrol_lti_upgrade($oldversion) { - global $CFG; + global $CFG, $DB; // Automatically generated Moodle v3.6.0 release upgrade line. // Put any upgrade step following this. @@ -57,5 +57,17 @@ function xmldb_enrol_lti_upgrade($oldversion) { // Automatically generated Moodle v3.11.0 release upgrade line. // Put any upgrade step following this. + if ($oldversion < 2021051701) { + // Disable all orphaned enrolment method instances. + $sql = "id IN (SELECT t.enrolid + FROM {enrol_lti_tools} t + LEFT JOIN {context} c ON (t.contextid = c.id) + WHERE c.id IS NULL)"; + $DB->set_field_select('enrol', 'status', 1, $sql); + + // Lti savepoint reached. + upgrade_plugin_savepoint(true, 2021051701, 'enrol', 'lti'); + } + return true; } diff --git a/enrol/lti/lib.php b/enrol/lti/lib.php index 421b5cd790a..82419613ec5 100644 --- a/enrol/lti/lib.php +++ b/enrol/lti/lib.php @@ -424,3 +424,18 @@ function enrol_lti_get_fontawesome_icon_map() { 'enrol_lti:enrolinstancewarning' => 'fa-exclamation-circle text-danger', ]; } + +/** + * Pre-delete course module hook which disables any methods referring to the deleted module, preventing launches and allowing remap. + * + * @param stdClass $cm The deleted course module record. + */ +function enrol_lti_pre_course_module_delete(stdClass $cm) { + global $DB; + $sql = "id IN (SELECT t.enrolid + FROM {enrol_lti_tools} t + JOIN {context} c ON (t.contextid = c.id) + WHERE c.contextlevel = :contextlevel + AND c.instanceid = :cmid)"; + $DB->set_field_select('enrol', 'status', ENROL_INSTANCE_DISABLED, $sql, ['contextlevel' => CONTEXT_MODULE, 'cmid' => $cm->id]); +} diff --git a/enrol/lti/tests/lib_test.php b/enrol/lti/tests/lib_test.php index 12b12033964..e74c1954e45 100644 --- a/enrol/lti/tests/lib_test.php +++ b/enrol/lti/tests/lib_test.php @@ -169,4 +169,36 @@ class lib_test extends \advanced_testcase { // LTI enrolment has 1 enrol actions for active users -- unenrol. $this->assertCount(1, $actions); } + + /** + * Test the behaviour of an enrolment method when the activity to which it provides access is deleted. + * + * @covers \enrol_lti_pre_course_module_delete + */ + public function test_course_module_deletion() { + // Create two modules and publish them. + $course = $this->getDataGenerator()->create_course(); + $mod = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); + $mod2 = $this->getDataGenerator()->create_module('assign', ['course' => $course->id]); + $tooldata = [ + 'cmid' => $mod->cmid, + 'courseid' => $course->id, + ]; + $tool = $this->getDataGenerator()->create_lti_tool((object)$tooldata); + $tooldata['cmid'] = $mod2->cmid; + $tool2 = $this->getDataGenerator()->create_lti_tool((object)$tooldata); + + // Verify the instances are both enabled. + $modinstance = helper::get_lti_tool($tool->id); + $mod2instance = helper::get_lti_tool($tool2->id); + $this->assertEquals(ENROL_INSTANCE_ENABLED, $modinstance->status); + $this->assertEquals(ENROL_INSTANCE_ENABLED, $mod2instance->status); + + // Delete a module and verify the associated instance is disabled. + course_delete_module($mod->cmid); + $modinstance = helper::get_lti_tool($tool->id); + $mod2instance = helper::get_lti_tool($tool2->id); + $this->assertEquals(ENROL_INSTANCE_DISABLED, $modinstance->status); + $this->assertEquals(ENROL_INSTANCE_ENABLED, $mod2instance->status); + } } diff --git a/enrol/lti/version.php b/enrol/lti/version.php index 2225d9847d8..4263f277d26 100644 --- a/enrol/lti/version.php +++ b/enrol/lti/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021051700; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2021051701; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2021051100; // Requires this Moodle version. $plugin->component = 'enrol_lti'; // Full name of the plugin (used for diagnostics).