MDL-71144 mod_quiz: custom_completion should not use deprecated function

This commit also removes an unnecessary DB query.
This commit is contained in:
Shamim Rezaie 2021-03-31 03:02:50 +11:00
parent d9d0ae01d3
commit 7d102bb67d
2 changed files with 79 additions and 26 deletions

View File

@ -18,7 +18,12 @@ declare(strict_types=1);
namespace mod_quiz\completion;
use context_module;
use core_completion\activity_custom_completion;
use grade_grade;
use grade_item;
use quiz;
use quiz_access_manager;
/**
* Activity custom completion subclass for the quiz activity.
@ -32,6 +37,75 @@ use core_completion\activity_custom_completion;
*/
class custom_completion extends activity_custom_completion {
/**
* Check passing grade (or no attempts left) requirement for completion.
*
* @return bool True if the passing grade (or no attempts left) requirement is disabled or met.
*/
protected function check_passing_grade_or_all_attempts(): bool {
global $CFG;
require_once($CFG->libdir . '/gradelib.php');
$completionpassorattempts = $this->cm->customdata['customcompletionrules']['completionpassorattemptsexhausted'];
if (empty($completionpassorattempts['completionpass'])) {
return true;
}
// Check for passing grade.
$item = grade_item::fetch([
'courseid' => $this->cm->get_course()->id,
'itemtype' => 'mod',
'itemmodule' => 'quiz',
'iteminstance' => $this->cm->instance,
'outcomeid' => null
]);
if ($item) {
$grades = grade_grade::fetch_users_grades($item, [$this->userid], false);
if (!empty($grades[$this->userid]) && $grades[$this->userid]->is_passed($item)) {
return true;
}
}
// If a passing grade is required and exhausting all available attempts is not accepted for completion,
// then this quiz is not complete.
if (empty($completionpassorattempts['completionattemptsexhausted'])) {
return false;
}
// Check if all attempts are used up.
$attempts = quiz_get_user_attempts($this->cm->instance, $this->userid, 'finished', true);
if (!$attempts) {
return false;
}
$lastfinishedattempt = end($attempts);
$context = context_module::instance($this->cm->id);
$quizobj = quiz::create($this->cm->instance, $this->userid);
$accessmanager = new quiz_access_manager(
$quizobj,
time(),
has_capability('mod/quiz:ignoretimelimits', $context, $this->userid, false)
);
return $accessmanager->is_finished(count($attempts), $lastfinishedattempt);
}
/**
* Check minimum attempts requirement for completion.
*
* @return bool True if minimum attempts requirement is disabled or met.
*/
protected function check_min_attempts() {
$minattempts = $this->cm->customdata['customcompletionrules']['completionminattempts'];
if (!$minattempts) {
return true;
}
// Check if the user has done enough attempts.
$attempts = quiz_get_user_attempts($this->cm->instance, $this->userid, 'finished', true);
return $minattempts <= count($attempts);
}
/**
* Fetches the completion state for a given completion rule.
*
@ -39,23 +113,14 @@ class custom_completion extends activity_custom_completion {
* @return int The completion state.
*/
public function get_state(string $rule): int {
global $DB;
$this->validate_rule($rule);
$quiz = $DB->get_record('quiz', ['id' => $this->cm->instance], '*', MUST_EXIST);
switch ($rule) {
case 'completionpassorattemptsexhausted':
$status = quiz_completion_check_passing_grade_or_all_attempts(
$this->cm->get_course(),
$this->cm,
$this->userid,
$quiz
);
$status = static::check_passing_grade_or_all_attempts();
break;
case 'completionminattempts':
$status = quiz_completion_check_min_attempts($this->userid, $quiz);
$status = static::check_min_attempts();
break;
}

View File

@ -254,14 +254,10 @@ class mod_quiz_lib_testcase extends advanced_testcase {
// Check the results.
$this->assertFalse(quiz_get_completion_state($course, $cm, $failstudent->id, 'return'));
$this->assertDebuggingCalledCount(7, [
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
$this->assertDebuggingCalledCount(3, [
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_min_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
]);
}
@ -317,15 +313,11 @@ class mod_quiz_lib_testcase extends advanced_testcase {
// Check the results. Quiz is completed by $exhauststudent because there are no remaining attempts.
$this->assertTrue(quiz_get_completion_state($course, $cm, $exhauststudent->id, 'return'));
$this->assertDebuggingCalledCount(9, [
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
$this->assertDebuggingCalledCount(5, [
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_min_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_min_attempts has been deprecated.',
]);
}
@ -422,11 +414,7 @@ class mod_quiz_lib_testcase extends advanced_testcase {
// Check the results. Quiz is completed by $student because two attempts were done AND a passing grade was obtained.
$this->assertTrue(quiz_get_completion_state($course, $cm, $student->id, 'return'));
$this->assertDebuggingCalledCount(8, [
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_min_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_min_attempts has been deprecated.',
$this->assertDebuggingCalledCount(4, [
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',
'quiz_completion_check_min_attempts has been deprecated.',
'quiz_completion_check_passing_grade_or_all_attempts has been deprecated.',