Skip to content

Commit

Permalink
MDL-71659 completion: Consider modules without grade_item incomplete
Browse files Browse the repository at this point in the history
Activity modules may not have the associated grade_item created yet. It
used to throw fatal error in that case - even when trying to view the
course or edit the activity. So there was no easy way to recover from
this situation.

The patch is based on reasoning that an activity without grade item is
same as activity without any grades. And as such it is considered
incomplete.

A new unit test is added to cover this specific scenario. The existing
unit test is modified and it does not expect the exception any more.
There does not seem to be any good reason why this situation should be
exceptional.
  • Loading branch information
mudrd8mz committed May 18, 2021
1 parent 3da88a7 commit a949a15
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 4 deletions.
3 changes: 0 additions & 3 deletions lib/completionlib.php
Expand Up @@ -769,9 +769,6 @@ public function get_grade_completion(cm_info $cm, int $userid): int {
item '{$item->id}', user '{$userid}'");
}
return self::internal_get_grade_state($item, reset($grades));
} else {
$this->internal_systemerror("Cannot find grade item for '{$cm->modname}'
cm '{$cm->id}' matching number '{$cm->completiongradeitemnumber}'");
}

return COMPLETION_INCOMPLETE;
Expand Down
40 changes: 39 additions & 1 deletion lib/tests/completionlib_test.php
Expand Up @@ -1266,7 +1266,7 @@ public function test_completion_can_view_data() {
*/
public function get_grade_completion_provider() {
return [
'Grade not required' => [false, false, null, moodle_exception::class, null],
'Grade not required' => [false, false, null, null, null],
'Grade required, but has no grade yet' => [true, false, null, null, COMPLETION_INCOMPLETE],
'Grade required, grade received' => [true, true, null, null, COMPLETION_COMPLETE],
'Grade required, passing grade received' => [true, true, 70, null, COMPLETION_COMPLETE_PASS],
Expand Down Expand Up @@ -1312,6 +1312,44 @@ public function test_get_grade_completion(bool $completionusegrade, bool $hasgra
$gradecompletion = $completioninfo->get_grade_completion($cm, $this->user->id);
$this->assertEquals($expectedresult, $gradecompletion);
}

/**
* Test the return value for cases when the activity module does not have associated grade_item.
*/
public function test_get_grade_completion_without_grade_item() {
global $DB;

$this->setup_data();

$assign = $this->getDataGenerator()->get_plugin_generator('mod_assign')->create_instance([
'course' => $this->course->id,
'completion' => COMPLETION_ENABLED,
'completionusegrade' => true,
'gradepass' => 42,
]);

$cm = cm_info::create(get_coursemodule_from_instance('assign', $assign->id));

$DB->delete_records('grade_items', [
'courseid' => $this->course->id,
'itemtype' => 'mod',
'itemmodule' => 'assign',
'iteminstance' => $assign->id,
]);

// Without the grade_item, the activity is considered incomplete.
$completioninfo = new completion_info($this->course);
$this->assertEquals(COMPLETION_INCOMPLETE, $completioninfo->get_grade_completion($cm, $this->user->id));

// Once the activity is graded, the grade_item is automatically created.
$assigninstance = new assign($cm->context, $cm, $this->course);
$grade = $assigninstance->get_user_grade($this->user->id, true);
$grade->grade = 40;
$assigninstance->update_grade($grade);

// The implicitly created grade_item does not have grade to pass defined so it is not distinguished.
$this->assertEquals(COMPLETION_COMPLETE, $completioninfo->get_grade_completion($cm, $this->user->id));
}
}

class core_completionlib_fake_recordset implements Iterator {
Expand Down

0 comments on commit a949a15

Please sign in to comment.