From 08344a8c4b7dbe4bdc8e00b1e1dcbdc7c259c01d Mon Sep 17 00:00:00 2001 From: Paul Holden Date: Tue, 22 Aug 2023 09:03:57 +0100 Subject: [PATCH] MDL-79073 question: detect missing context when deleting question. --- lib/questionlib.php | 3 ++- lib/tests/questionlib_test.php | 27 +++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/questionlib.php b/lib/questionlib.php index 762b7d30081..736e359a6e6 100644 --- a/lib/questionlib.php +++ b/lib/questionlib.php @@ -352,11 +352,12 @@ function question_delete_question($questionid): void { qv.version, qbe.id as entryid, qc.id as categoryid, - qc.contextid as contextid + ctx.id as contextid FROM {question} q LEFT JOIN {question_versions} qv ON qv.questionid = q.id LEFT JOIN {question_bank_entries} qbe ON qbe.id = qv.questionbankentryid LEFT JOIN {question_categories} qc ON qc.id = qbe.questioncategoryid + LEFT JOIN {context} ctx ON ctx.id = qc.contextid WHERE q.id = ?'; $questiondata = $DB->get_record_sql($sql, [$question->id]); diff --git a/lib/tests/questionlib_test.php b/lib/tests/questionlib_test.php index 1b93d96d59d..0c0bebc91d2 100644 --- a/lib/tests/questionlib_test.php +++ b/lib/tests/questionlib_test.php @@ -322,6 +322,33 @@ class questionlib_test extends \advanced_testcase { $this->assertFalse($DB->record_exists('question', ['id' => $q1->id])); } + /** + * Test deleting a broken question whose category refers to a missing context + */ + public function test_question_delete_question_missing_context() { + global $DB; + + $coursecategory = $this->getDataGenerator()->create_category(); + $context = $coursecategory->get_context(); + + /** @var \core_question_generator $generator */ + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $questioncategory = $generator->create_question_category(['contextid' => $context->id]); + $question = $generator->create_question('shortanswer', null, ['category' => $questioncategory->id]); + + // Now delete the context, to simulate what happens in old sites where + // referential integrity has failed. + $DB->delete_records('context', ['id' => $context->id]); + + question_delete_question($question->id); + + $this->assertDebuggingCalled('Deleting question ' . $question->id . + ' which is no longer linked to a context. Assuming system context ' . + 'to avoid errors, but this may mean that some data like ' . + 'files, tags, are not cleaned up.'); + $this->assertFalse($DB->record_exists('question', ['id' => $question->id])); + } + /** * This function tests the question_category_delete_safe function. */