This commit is contained in:
Jun Pataleta
2025-08-07 10:39:11 +08:00
3 changed files with 58 additions and 10 deletions
+5
View File
@@ -746,6 +746,8 @@ function course_delete_module($cmid, $async = false) {
"Cannot delete this module as the file mod/$modulename/lib.php is missing.");
}
// Warning! there is very similar code in remove_course_contents.
// If you are changing this code, you probably need to change that too.
$deleteinstancefunction = $modulename . '_delete_instance';
// Ensure the delete_instance function exists for this module.
@@ -774,6 +776,9 @@ function course_delete_module($cmid, $async = false) {
"Cannot delete the module $modulename (instance).");
}
// We delete the questions after the activity database is removed,
// because questions are referenced via question reference tables
// and cannot be deleted while the activities that use them still exist.
question_delete_activity($cm);
// Remove all module files in case modules forget to do that.
+12 -10
View File
@@ -4834,16 +4834,8 @@ function remove_course_contents($courseid, $showfeedback = true, ?array $options
if ($instances) {
foreach ($instances as $cm) {
if ($cm->id) {
// Delete activity context questions and question categories.
question_delete_activity($cm, coursedeletion: $coursedeletion);
// Notify the competency subsystem.
\core_competency\api::hook_course_module_deleted($cm);
// Delete all tag instances associated with the instance of this module.
core_tag_tag::delete_instances("mod_{$modname}", null, context_module::instance($cm->id)->id);
core_tag_tag::remove_all_item_tags('core', 'course_modules', $cm->id);
}
// Warning! there is very similar code in course_delete_module.
// If you are changing this code, you probably need to change that too.
if (function_exists($moddelete)) {
// This purges all module data in related tables, extra user prefs, settings, etc.
$moddelete($cm->modinstance);
@@ -4854,6 +4846,16 @@ function remove_course_contents($courseid, $showfeedback = true, ?array $options
}
if ($cm->id) {
// Delete activity context questions and question categories.
// We delete the questions after the activity database is removed,
// because questions are referenced via question reference tables
// and cannot be deleted while the activities that use them still exist.
question_delete_activity($cm, coursedeletion: $coursedeletion);
// Delete all tag instances associated with the instance of this module.
core_tag_tag::delete_instances("mod_{$modname}", null, context_module::instance($cm->id)->id);
core_tag_tag::remove_all_item_tags('core', 'course_modules', $cm->id);
// Notify the competency subsystem.
\core_competency\api::hook_course_module_deleted($cm);
// Delete cm and its context - orphaned contexts are purged in cron in case of any race condition.
context_helper::delete_instance(CONTEXT_MODULE, $cm->id);
$DB->delete_records('course_modules_completion', ['coursemoduleid' => $cm->id]);
+41
View File
@@ -139,6 +139,47 @@ final class lib_test extends \advanced_testcase {
$this->assertEquals(0, $DB->count_records('question_set_references', ['usingcontextid' => $context->id]));
}
/**
* Test deleting a quiz when the course is deleted.
*
* @covers ::quiz_delete_instance
*/
public function test_quiz_when_delete_course(): void {
global $DB, $USER;
$this->resetAfterTest();
$this->setAdminUser();
// Step 1: Create one course and a user with editing teacher capabilities.
$generator = $this->getDataGenerator();
$course = $generator->create_course();
$teacher = $USER;
$generator->enrol_user($teacher->id, $course->id, 'editingteacher');
// Create a quiz with questions in the first course.
$quiz = $this->create_test_quiz($course);
$context = \context_module::instance($quiz->cmid);
// Create questions.
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
$cat = $questiongenerator->create_question_category(['contextid' => $context->id]);
$saq = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
// Add to the quiz.
quiz_add_quiz_question($saq->id, $quiz);
// Delete the course.
delete_course($course, false);
// Check that the question was deleted.
$this->assertFalse($DB->record_exists('question', ['id' => $saq->id]));
// Check that all the slots were removed.
$this->assertFalse($DB->record_exists('quiz_slots', ['quizid' => $quiz->id]));
// Check that the quiz was removed.
$this->assertFalse($DB->record_exists('quiz', ['id' => $quiz->id]));
// Check that any question references linked to this quiz are gone.
$this->assertFalse($DB->record_exists('question_references', ['usingcontextid' => $context->id]));
$this->assertFalse($DB->record_exists('question_set_references', ['usingcontextid' => $context->id]));
}
public function test_quiz_get_user_attempts(): void {
global $DB;
$this->resetAfterTest();