From 563cfa0e1e530edbea73a9c51ed18cc5c50812ce Mon Sep 17 00:00:00 2001 From: Nathan Nguyen Date: Tue, 12 May 2020 16:21:56 +1000 Subject: [PATCH] MDL-68680 core_grades: check grade item before trigger delete event --- lib/grade/grade_grade.php | 13 ++++-- lib/grade/tests/grade_grade_test.php | 64 ++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/lib/grade/grade_grade.php b/lib/grade/grade_grade.php index 832546a0beb..13d2ad5bf96 100644 --- a/lib/grade/grade_grade.php +++ b/lib/grade/grade_grade.php @@ -252,6 +252,10 @@ class grade_grade extends grade_object { $this->grade_item = grade_item::fetch(array('id'=>$this->itemid)); } + if (empty($this->grade_item)) { + debugging("Missing grade item id $this->itemid", DEBUG_DEVELOPER); + } + return $this->grade_item; } @@ -1117,8 +1121,7 @@ class grade_grade extends grade_object { $success = parent::delete($source); // If the grade was deleted successfully trigger a grade_deleted event. - if ($success) { - $this->load_grade_item(); + if ($success && !empty($this->grade_item)) { \core\event\grade_deleted::create_from_grade($this)->trigger(); } @@ -1157,8 +1160,10 @@ class grade_grade extends grade_object { return; } - // Load information about grade item - $this->load_grade_item(); + // Load information about grade item, exit if the grade item is missing. + if (!$this->load_grade_item()) { + return; + } // Only course-modules have completion data if ($this->grade_item->itemtype!='mod') { diff --git a/lib/grade/tests/grade_grade_test.php b/lib/grade/tests/grade_grade_test.php index d3980330768..5a003f5bdd9 100644 --- a/lib/grade/tests/grade_grade_test.php +++ b/lib/grade/tests/grade_grade_test.php @@ -40,6 +40,7 @@ class core_grade_grade_testcase extends grade_base_testcase { $this->sub_test_grade_grade_set_hidden(); $this->sub_test_grade_grade_is_hidden(); $this->sub_test_grade_grade_deleted(); + $this->sub_test_grade_grade_deleted_event(); } protected function sub_test_grade_grade_construct() { @@ -506,4 +507,67 @@ class core_grade_grade_testcase extends grade_base_testcase { $fs = get_file_storage(); $fs->create_file_from_string($dummy, ''); } + + /** + * Tests grade_deleted event. + */ + public function sub_test_grade_grade_deleted_event() { + global $DB; + $dg = $this->getDataGenerator(); + + // Create the data we need for the tests. + $u1 = $dg->create_user(); + $u2 = $dg->create_user(); + $c1 = $dg->create_course(); + $a1 = $dg->create_module('assign', ['course' => $c1->id]); + + $gi = new grade_item($dg->create_grade_item( + [ + 'courseid' => $c1->id, + 'itemtype' => 'mod', + 'itemmodule' => 'assign', + 'iteminstance' => $a1->id + ] + ), false); + + grade_update('mod/assign', $gi->courseid, $gi->itemtype, $gi->itemmodule, $gi->iteminstance, + $gi->itemnumber, ['userid' => $u1->id]); + grade_update('mod/assign', $gi->courseid, $gi->itemtype, $gi->itemmodule, $gi->iteminstance, + $gi->itemnumber, ['userid' => $u2->id]); + + $gg = grade_grade::fetch(array('userid' => $u1->id, 'itemid' => $gi->id)); + $this->assertEquals($u1->id, $gg->userid); + $gg->load_grade_item(); + $this->assertEquals($gi->id, $gg->grade_item->id); + + // Delete user with valid grade item. + $sink = $this->redirectEvents(); + grade_user_delete($u1->id); + $events = $sink->get_events(); + $event = reset($events); + $sink->close(); + $this->assertInstanceOf('core\event\grade_deleted', $event); + + $gg = grade_grade::fetch(array('userid' => $u2->id, 'itemid' => $gi->id)); + $this->assertEquals($u2->id, $gg->userid); + $gg->load_grade_item(); + $this->assertEquals($gi->id, $gg->grade_item->id); + + // Delete grade item, mock up orphaned grade_grades. + $DB->delete_records('grade_items', ['id' => $gi->id]); + $gg = grade_grade::fetch(array('userid' => $u2->id, 'itemid' => $gi->id)); + $this->assertEquals($u2->id, $gg->userid); + + // No event is triggered and there is a debugging message. + $sink = $this->redirectEvents(); + grade_user_delete($u2->id); + $this->assertDebuggingCalled("Missing grade item id $gi->id"); + $events = $sink->get_events(); + $sink->close(); + $this->assertEmpty($events); + + // The grade should be deleted. + $gg = grade_grade::fetch(array('userid' => $u2->id, 'itemid' => $gi->id)); + $this->assertEmpty($gg); + } } -- 2.43.0