MDL-78608 question stats: avoid loading data for missing contexts

It turns out that there are plugins which don't (currently)
clean up their question attempts when a context is deleted.
Therefore, we need to make Moodle core robust to that.
This commit is contained in:
Tim Hunt
2023-06-29 16:27:01 +01:00
parent eb1fab720a
commit 2a2dd08ff1
2 changed files with 15 additions and 0 deletions
@@ -103,6 +103,7 @@ class statistics_bulk_loader {
SELECT MIN(qu.id) AS somethingunique, qu.component, qu.contextid
FROM {question_usages} qu
JOIN {question_attempts} qatt ON qatt.questionusageid = qu.id
JOIN {context} ctx ON ctx.id = qu.contextid
WHERE qatt.questionid $questionidcondition
GROUP BY qu.component, qu.contextid
ORDER BY qu.contextid ASC
@@ -49,6 +49,7 @@ class statistics_bulk_loader_test extends advanced_testcase {
* @covers ::get_all_places_where_questions_were_attempted
*/
public function test_get_all_places_where_questions_were_attempted(): void {
global $DB;
$this->resetAfterTest();
$this->setAdminUser();
@@ -122,6 +123,19 @@ class statistics_bulk_loader_test extends advanced_testcase {
$newplace = end($q2places);
}
$this->assertEquals((object) ['component' => 'mod_quiz', 'contextid' => $quiz3context->id], $newplace);
// Simulate the situation where the context for quiz3 is gone from the database, without
// the corresponding attempt data being properly cleaned up. Ensure this does not cause errors.
$DB->delete_records('context', ['id' => context_module::instance($quiz3->cmid)->id]);
accesslib_clear_all_caches_for_unit_testing();
// Same asserts as above, before we added quiz3.
$q1places = $rcm->invoke(null, [$question1->id]);
$this->assertCount(2, $q1places);
$this->assertEquals((object) ['component' => 'mod_quiz', 'contextid' => $quiz1context->id], $q1places[0]);
$this->assertEquals((object) ['component' => 'mod_quiz', 'contextid' => $quiz2context->id], $q1places[1]);
$q2places = $rcm->invoke(null, [$question2->id]);
$this->assertCount(1, $q2places);
$this->assertEquals((object) ['component' => 'mod_quiz', 'contextid' => $quiz2context->id], $q2places[0]);
}
/**