Commit cd52b46e authored by Peter Dias's avatar Peter Dias
Browse files

MDL-52206 quiz: Remove completionpass completion from quiz

AMOS BEGIN
 MOV [completionpass,mod_quiz],[completionpassgrade,core_completion]
 MOV [completionpassdesc,mod_quiz],[completionpassgrade_desc,core_completion]
 MOV [completionpass_help,mod_quiz],[completionpassgrade_help,core_completion]
AMOS END
parent 90acd8d3
...@@ -25,8 +25,8 @@ Feature: Award badges based on activity completion ...@@ -25,8 +25,8 @@ Feature: Award badges based on activity completion
| questioncategory | qtype | name | questiontext | | questioncategory | qtype | name | questiontext |
| Test questions | truefalse | First question | Answer the first question | | Test questions | truefalse | First question | Answer the first question |
And the following "activities" exist: And the following "activities" exist:
| activity | name | course | idnumber | attempts | gradepass | completion | completionattemptsexhausted | completionpass | completionusegrade | | activity | name | course | idnumber | attempts | gradepass | completion | completionattemptsexhausted | completionpassgrade | completionusegrade |
| quiz | Test quiz name | C1 | quiz1 | 2 | 5.00 | 2 | 1 | 1 | 1 | | quiz | Test quiz name | C1 | quiz1 | 2 | 5.00 | 2 | 1 | 1 | 1 |
And quiz "Test quiz name" contains the following questions: And quiz "Test quiz name" contains the following questions:
| question | page | | question | page |
| First question | 1 | | First question | 1 |
...@@ -53,7 +53,8 @@ Feature: Award badges based on activity completion ...@@ -53,7 +53,8 @@ Feature: Award badges based on activity completion
Scenario: Student earns a badge using activity completion, but does not get passing grade Scenario: Student earns a badge using activity completion, but does not get passing grade
Given I log in as "student1" Given I log in as "student1"
And I am on "Course 1" course homepage And I am on "Course 1" course homepage
And the "Receive a grade" completion condition of "Test quiz name" is displayed as "failed" And the "Receive a grade" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "failed"
And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo" And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo"
When I am on the "Test quiz name" "quiz activity" page When I am on the "Test quiz name" "quiz activity" page
And I press "Re-attempt quiz" And I press "Re-attempt quiz"
......
...@@ -80,7 +80,7 @@ class core_completion_bulk_update_testcase extends advanced_testcase { ...@@ -80,7 +80,7 @@ class core_completion_bulk_update_testcase extends advanced_testcase {
'lti-2' => ['lti', ['completion' => COMPLETION_TRACKING_MANUAL]], 'lti-2' => ['lti', ['completion' => COMPLETION_TRACKING_MANUAL]],
'page-1' => ['page', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1]], 'page-1' => ['page', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1]],
'page-2' => ['page', ['completion' => COMPLETION_TRACKING_MANUAL]], 'page-2' => ['page', ['completion' => COMPLETION_TRACKING_MANUAL]],
'quiz-1' => ['quiz', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionpass' => 1]], 'quiz-1' => ['quiz', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionpassgrade' => 1]],
'quiz-2' => ['quiz', ['completion' => COMPLETION_TRACKING_MANUAL]], 'quiz-2' => ['quiz', ['completion' => COMPLETION_TRACKING_MANUAL]],
'resource-1' => ['resource', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1]], 'resource-1' => ['resource', ['completion' => COMPLETION_TRACKING_AUTOMATIC, 'completionview' => 1]],
'resource-2' => ['resource', ['completion' => COMPLETION_TRACKING_MANUAL]], 'resource-2' => ['resource', ['completion' => COMPLETION_TRACKING_MANUAL]],
......
...@@ -49,7 +49,7 @@ class backup_quiz_activity_structure_step extends backup_questions_activity_stru ...@@ -49,7 +49,7 @@ class backup_quiz_activity_structure_step extends backup_questions_activity_stru
'questionsperpage', 'navmethod', 'shuffleanswers', 'questionsperpage', 'navmethod', 'shuffleanswers',
'sumgrades', 'grade', 'timecreated', 'sumgrades', 'grade', 'timecreated',
'timemodified', 'password', 'subnet', 'browsersecurity', 'timemodified', 'password', 'subnet', 'browsersecurity',
'delay1', 'delay2', 'showuserpicture', 'showblocks', 'completionattemptsexhausted', 'completionpass', 'delay1', 'delay2', 'showuserpicture', 'showblocks', 'completionattemptsexhausted',
'completionminattempts', 'allowofflineattempts')); 'completionminattempts', 'allowofflineattempts'));
// Define elements for access rule subplugin settings. // Define elements for access rule subplugin settings.
......
...@@ -292,6 +292,12 @@ class restore_quiz_activity_structure_step extends restore_questions_activity_st ...@@ -292,6 +292,12 @@ class restore_quiz_activity_structure_step extends restore_questions_activity_st
$DB->insert_record('quizaccess_seb_quizsettings', $sebsettings); $DB->insert_record('quizaccess_seb_quizsettings', $sebsettings);
} }
// If we are dealing with a backup from < 4.0 then we need to move completionpass to core.
if (!empty($data->completionpass)) {
$params = ['id' => $this->task->get_moduleid()];
$DB->set_field('course_modules', 'completionpassgrade', $data->completionpass, $params);
}
} }
protected function process_quiz_question_instance($data) { protected function process_quiz_question_instance($data) {
......
...@@ -131,9 +131,12 @@ class mod_quiz_external extends external_api { ...@@ -131,9 +131,12 @@ class mod_quiz_external extends external_api {
'reviewspecificfeedback', 'reviewgeneralfeedback', 'reviewrightanswer', 'reviewspecificfeedback', 'reviewgeneralfeedback', 'reviewrightanswer',
'reviewoverallfeedback', 'questionsperpage', 'navmethod', 'reviewoverallfeedback', 'questionsperpage', 'navmethod',
'browsersecurity', 'delay1', 'delay2', 'showuserpicture', 'showblocks', 'browsersecurity', 'delay1', 'delay2', 'showuserpicture', 'showblocks',
'completionattemptsexhausted', 'completionpass', 'overduehandling', 'completionattemptsexhausted', 'overduehandling',
'graceperiod', 'canredoquestions', 'allowofflineattempts'); 'graceperiod', 'canredoquestions', 'allowofflineattempts');
$viewablefields = array_merge($viewablefields, $additionalfields); $viewablefields = array_merge($viewablefields, $additionalfields);
// Any course module fields that previously existed in quiz.
$quizdetails['completionpass'] = $quizobj->get_cm()->completionpassgrade;
} }
// Fields only for managers. // Fields only for managers.
......
<?xml version="1.0" encoding="UTF-8" ?> <?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/quiz/db" VERSION="20200615" COMMENT="XMLDB file for Moodle mod/quiz" <XMLDB PATH="mod/quiz/db" VERSION="20200630" COMMENT="XMLDB file for Moodle mod/quiz"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd" xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
> >
...@@ -45,7 +45,6 @@ ...@@ -45,7 +45,6 @@
<FIELD NAME="showuserpicture" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Option to show the user's picture during the attempt and on the review page."/> <FIELD NAME="showuserpicture" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Option to show the user's picture during the attempt and on the review page."/>
<FIELD NAME="showblocks" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether blocks should be shown on the attempt.php and review.php pages."/> <FIELD NAME="showblocks" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Whether blocks should be shown on the attempt.php and review.php pages."/>
<FIELD NAME="completionattemptsexhausted" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="completionattemptsexhausted" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="completionpass" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="completionminattempts" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="completionminattempts" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="allowofflineattempts" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Whether to allow the quiz to be attempted offline in the mobile app"/> <FIELD NAME="allowofflineattempts" TYPE="int" LENGTH="1" NOTNULL="false" DEFAULT="0" SEQUENCE="false" COMMENT="Whether to allow the quiz to be attempted offline in the mobile app"/>
</FIELDS> </FIELDS>
......
...@@ -60,5 +60,45 @@ function xmldb_quiz_upgrade($oldversion) { ...@@ -60,5 +60,45 @@ function xmldb_quiz_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2020061501, 'quiz'); upgrade_mod_savepoint(true, 2020061501, 'quiz');
} }
if ($oldversion < 2021052503) {
$table = new xmldb_table('quiz');
$field = new xmldb_field('completionpass');
if ($dbman->field_exists($table, $field)) {
$sql = "SELECT q.id " .
"FROM {quiz} q " .
"INNER JOIN {course_modules} cm ON cm.instance = q.id " .
"INNER JOIN {modules} m ON m.id = cm.module " .
"WHERE m.name = :name AND q.completionpass = :completionpass";
/** @var moodle_recordset $records */
$records = $DB->get_recordset_sql($sql, ['name' => 'quiz', 'completionpass' => 1], 0, 1000);
while ($records->valid()) {
foreach ($records as $record) {
$ids[] = $record->id;
}
if ($ids) {
list($insql, $params) = $DB->get_in_or_equal($ids, SQL_PARAMS_NAMED);
$DB->set_field_select('course_modules', 'completionpassgrade', 1, "instance $insql", $params);
// Reset the value so it doesn't get picked on the next run. The field will be dropped later.
$DB->set_field_select('quiz', 'completionpass', 0, "id $insql", $params);
// Get the next batch of records.
$records = $DB->get_recordset_sql($sql, ['name' => 'quiz', 'completionpass' => 1], 0, 1000);
}
}
$records->close();
// We have completed our checks. Drop the field.
if ($dbman->field_exists($table, $field)) {
$dbman->drop_field($table, $field);
}
}
upgrade_mod_savepoint(true, 2021052503, 'quiz');
}
return true; return true;
} }
...@@ -40,7 +40,7 @@ function quiz_completion_check_passing_grade_or_all_attempts($course, $cm, $user ...@@ -40,7 +40,7 @@ function quiz_completion_check_passing_grade_or_all_attempts($course, $cm, $user
debugging('quiz_completion_check_passing_grade_or_all_attempts has been deprecated.', DEBUG_DEVELOPER); debugging('quiz_completion_check_passing_grade_or_all_attempts has been deprecated.', DEBUG_DEVELOPER);
if (!$quiz->completionpass) { if (!$cm->completionpassgrade) {
return true; return true;
} }
...@@ -118,7 +118,7 @@ function quiz_get_completion_state($course, $cm, $userid, $type) { ...@@ -118,7 +118,7 @@ function quiz_get_completion_state($course, $cm, $userid, $type) {
// No need to call debugging here. Deprecation debugging notice already being called in \completion_info::internal_get_state(). // No need to call debugging here. Deprecation debugging notice already being called in \completion_info::internal_get_state().
$quiz = $DB->get_record('quiz', array('id' => $cm->instance), '*', MUST_EXIST); $quiz = $DB->get_record('quiz', array('id' => $cm->instance), '*', MUST_EXIST);
if (!$quiz->completionattemptsexhausted && !$quiz->completionpass && !$quiz->completionminattempts) { if (!$quiz->completionattemptsexhausted && !$cm->completionpassgrade && !$quiz->completionminattempts) {
return $type; return $type;
} }
......
...@@ -2,3 +2,8 @@ numattemptsmade,mod_quiz ...@@ -2,3 +2,8 @@ numattemptsmade,mod_quiz
reviewofattempt,mod_quiz reviewofattempt,mod_quiz
reviewofpreview,mod_quiz reviewofpreview,mod_quiz
settingsoverrides,mod_quiz settingsoverrides,mod_quiz
completionpass,mod_quiz
completionpassdesc,mod_quiz
completionpass_help,mod_quiz
completiondetail:passgrade,mod_quiz
gradetopassnotset,mod_quiz
...@@ -181,15 +181,11 @@ $string['commentorgrade'] = 'Make comment or override grade'; ...@@ -181,15 +181,11 @@ $string['commentorgrade'] = 'Make comment or override grade';
$string['comments'] = 'Comments'; $string['comments'] = 'Comments';
$string['completedon'] = 'Completed on'; $string['completedon'] = 'Completed on';
$string['completiondetail:minattempts'] = 'Make attempts: {$a}'; $string['completiondetail:minattempts'] = 'Make attempts: {$a}';
$string['completiondetail:passgrade'] = 'Receive a pass grade';
$string['completiondetail:passorexhaust'] = 'Receive a pass grade or complete all available attempts'; $string['completiondetail:passorexhaust'] = 'Receive a pass grade or complete all available attempts';
$string['completionminattempts'] = 'Minimum number of attempts:'; $string['completionminattempts'] = 'Minimum number of attempts:';
$string['completionminattemptsdesc'] = 'Minimum number of attempts required: {$a}'; $string['completionminattemptsdesc'] = 'Minimum number of attempts required: {$a}';
$string['completionminattemptsgroup'] = 'Require attempts'; $string['completionminattemptsgroup'] = 'Require attempts';
$string['completionminattemptserror'] = 'Minimum number of attempts must be lower or equal to attempts allowed.'; $string['completionminattemptserror'] = 'Minimum number of attempts must be lower or equal to attempts allowed.';
$string['completionpass'] = 'Require passing grade';
$string['completionpassdesc'] = 'Student must achieve a passing grade to complete this activity';
$string['completionpass_help'] = 'If enabled, this activity is considered complete when the student receives a pass grade (as specified in the Grade section of the quiz settings) or higher.';
$string['completionpassorattemptsexhausteddesc'] = 'Student must achieve a passing grade, or exhaust all available attempts to complete this activity'; $string['completionpassorattemptsexhausteddesc'] = 'Student must achieve a passing grade, or exhaust all available attempts to complete this activity';
$string['completionattemptsexhausted'] = 'Or all available attempts completed'; $string['completionattemptsexhausted'] = 'Or all available attempts completed';
$string['completionattemptsexhausted_help'] = 'Mark quiz complete when the student has exhausted the maximum number of attempts.'; $string['completionattemptsexhausted_help'] = 'Mark quiz complete when the student has exhausted the maximum number of attempts.';
...@@ -421,7 +417,6 @@ $string['grademethod_help'] = 'When multiple attempts are allowed, the following ...@@ -421,7 +417,6 @@ $string['grademethod_help'] = 'When multiple attempts are allowed, the following
* Last attempt (all other attempts are ignored)'; * Last attempt (all other attempts are ignored)';
$string['gradesdeleted'] = 'Quiz grades deleted'; $string['gradesdeleted'] = 'Quiz grades deleted';
$string['gradesofar'] = '{$a->method}: {$a->mygrade} / {$a->quizgrade}.'; $string['gradesofar'] = '{$a->method}: {$a->mygrade} / {$a->quizgrade}.';
$string['gradetopassnotset'] = 'This quiz does not yet have a grade to pass set. It may be set in the Grade section of the quiz settings.';
$string['gradetopassmustbeset'] = 'Grade to pass cannot be zero as this quiz has its completion method set to require passing grade. Please set a non-zero value.'; $string['gradetopassmustbeset'] = 'Grade to pass cannot be zero as this quiz has its completion method set to require passing grade. Please set a non-zero value.';
$string['gradetopassoutof'] = 'Grade to pass: {$a->grade} out of {$a->maxgrade}'; $string['gradetopassoutof'] = 'Grade to pass: {$a->grade} out of {$a->maxgrade}';
$string['gradingdetails'] = 'Marks for this submission: {$a->raw}/{$a->max}.'; $string['gradingdetails'] = 'Marks for this submission: {$a->raw}/{$a->max}.';
...@@ -1037,3 +1032,10 @@ $string['settingsoverrides'] = 'Settings overrides'; ...@@ -1037,3 +1032,10 @@ $string['settingsoverrides'] = 'Settings overrides';
// Deprecated since Moodle 3.11. // Deprecated since Moodle 3.11.
$string['completionattemptsexhausteddesc'] = 'Complete if all available attempts are exhausted'; $string['completionattemptsexhausteddesc'] = 'Complete if all available attempts are exhausted';
// Deprecated since Moodle 4.0.
$string['completionpass'] = 'Require passing grade';
$string['completionpassdesc'] = 'Student must achieve a passing grade to complete this activity';
$string['completionpass_help'] = 'If enabled, this activity is considered complete when the student receives a pass grade (as specified in the Grade section of the quiz settings) or higher.';
$string['completiondetail:passgrade'] = 'Receive a pass grade';
$string['gradetopassnotset'] = 'This quiz does not yet have a grade to pass set. It may be set in the Grade section of the quiz settings.';
...@@ -1129,9 +1129,9 @@ function quiz_process_options($quiz) { ...@@ -1129,9 +1129,9 @@ function quiz_process_options($quiz) {
// Ensure that disabled checkboxes in completion settings are set to 0. // Ensure that disabled checkboxes in completion settings are set to 0.
if (empty($quiz->completionusegrade)) { if (empty($quiz->completionusegrade)) {
$quiz->completionpass = 0; $quiz->completionpassgrade = 0;
} }
if (empty($quiz->completionpass)) { if (empty($quiz->completionpassgrade)) {
$quiz->completionattemptsexhausted = 0; $quiz->completionattemptsexhausted = 0;
} }
if (empty($quiz->completionminattemptsenabled)) { if (empty($quiz->completionminattemptsenabled)) {
...@@ -2092,7 +2092,7 @@ function quiz_get_coursemodule_info($coursemodule) { ...@@ -2092,7 +2092,7 @@ function quiz_get_coursemodule_info($coursemodule) {
global $DB; global $DB;
$dbparams = ['id' => $coursemodule->instance]; $dbparams = ['id' => $coursemodule->instance];
$fields = 'id, name, intro, introformat, completionattemptsexhausted, completionpass, completionminattempts, $fields = 'id, name, intro, introformat, completionattemptsexhausted, completionminattempts,
timeopen, timeclose'; timeopen, timeclose';
if (!$quiz = $DB->get_record('quiz', $dbparams, $fields)) { if (!$quiz = $DB->get_record('quiz', $dbparams, $fields)) {
return false; return false;
...@@ -2108,9 +2108,9 @@ function quiz_get_coursemodule_info($coursemodule) { ...@@ -2108,9 +2108,9 @@ function quiz_get_coursemodule_info($coursemodule) {
// Populate the custom completion rules as key => value pairs, but only if the completion mode is 'automatic'. // Populate the custom completion rules as key => value pairs, but only if the completion mode is 'automatic'.
if ($coursemodule->completion == COMPLETION_TRACKING_AUTOMATIC) { if ($coursemodule->completion == COMPLETION_TRACKING_AUTOMATIC) {
if ($quiz->completionpass || $quiz->completionattemptsexhausted) { if ($quiz->completionattemptsexhausted) {
$result->customdata['customcompletionrules']['completionpassorattemptsexhausted'] = [ $result->customdata['customcompletionrules']['completionpassorattemptsexhausted'] = [
'completionpass' => $quiz->completionpass, 'completionpassgrade' => $coursemodule->completionpassgrade,
'completionattemptsexhausted' => $quiz->completionattemptsexhausted, 'completionattemptsexhausted' => $quiz->completionattemptsexhausted,
]; ];
} else { } else {
...@@ -2206,16 +2206,11 @@ function mod_quiz_get_completion_active_rule_descriptions($cm) { ...@@ -2206,16 +2206,11 @@ function mod_quiz_get_completion_active_rule_descriptions($cm) {
if (!empty($rules['completionpassorattemptsexhausted'])) { if (!empty($rules['completionpassorattemptsexhausted'])) {
if (!empty($rules['completionpassorattemptsexhausted']['completionattemptsexhausted'])) { if (!empty($rules['completionpassorattemptsexhausted']['completionattemptsexhausted'])) {
$descriptions[] = get_string('completionpassorattemptsexhausteddesc', 'quiz'); $descriptions[] = get_string('completionpassorattemptsexhausteddesc', 'quiz');
} else if (!empty($rules['completionpassorattemptsexhausted']['completionpass'])) {
$descriptions[] = get_string('completionpassdesc', 'quiz',
format_time($rules['completionpassorattemptsexhausted']['completionpass']));
} }
} else { } else {
// Fallback. // Fallback.
if (!empty($rules['completionattemptsexhausted'])) { if (!empty($rules['completionattemptsexhausted'])) {
$descriptions[] = get_string('completionpassorattemptsexhausteddesc', 'quiz'); $descriptions[] = get_string('completionpassorattemptsexhausteddesc', 'quiz');
} else if (!empty($rules['completionpass'])) {
$descriptions[] = get_string('completionpassdesc', 'quiz', format_time($rules['completionpass']));
} }
} }
......
...@@ -1877,7 +1877,7 @@ function quiz_attempt_submitted_handler($event) { ...@@ -1877,7 +1877,7 @@ function quiz_attempt_submitted_handler($event) {
// Update completion state. // Update completion state.
$completion = new completion_info($course); $completion = new completion_info($course);
if ($completion->is_enabled($cm) && if ($completion->is_enabled($cm) &&
($quiz->completionattemptsexhausted || $quiz->completionpass || $quiz->completionminattempts)) { ($quiz->completionattemptsexhausted || $quiz->completionminattempts)) {
$completion->update_state($cm, COMPLETION_COMPLETE, $event->userid); $completion->update_state($cm, COMPLETION_COMPLETE, $event->userid);
} }
return quiz_send_notification_messages($course, $quiz, $attempt, return quiz_send_notification_messages($course, $quiz, $attempt,
......
...@@ -527,19 +527,6 @@ class mod_quiz_mod_form extends moodleform_mod { ...@@ -527,19 +527,6 @@ class mod_quiz_mod_form extends moodleform_mod {
} }
} }
if (array_key_exists('completion', $data) && $data['completion'] == COMPLETION_TRACKING_AUTOMATIC) {
$completionpass = isset($data['completionpass']) ? $data['completionpass'] : $this->current->completionpass;
// Show an error if require passing grade was selected and the grade to pass was set to 0.
if ($completionpass && (empty($data['gradepass']) || grade_floatval($data['gradepass']) == 0)) {
if (isset($data['completionpass'])) {
$errors['completionpassgroup'] = get_string('gradetopassnotset', 'quiz');
} else {
$errors['gradepass'] = get_string('gradetopassmustbeset', 'quiz');
}
}
}
if (!empty($data['completionminattempts'])) { if (!empty($data['completionminattempts'])) {
if ($data['attempts'] > 0 && $data['completionminattempts'] > $data['attempts']) { if ($data['attempts'] > 0 && $data['completionminattempts'] > $data['attempts']) {
$errors['completionminattemptsgroup'] = get_string('completionminattemptserror', 'quiz'); $errors['completionminattemptsgroup'] = get_string('completionminattemptserror', 'quiz');
...@@ -615,17 +602,11 @@ class mod_quiz_mod_form extends moodleform_mod { ...@@ -615,17 +602,11 @@ class mod_quiz_mod_form extends moodleform_mod {
$mform = $this->_form; $mform = $this->_form;
$items = array(); $items = array();
$group = array(); $mform->addElement('advcheckbox', 'completionattemptsexhausted', null,
$group[] = $mform->createElement('advcheckbox', 'completionpass', null, get_string('completionpass', 'quiz'), get_string('completionattemptsexhausted', 'quiz'),
array('group' => 'cpass')); array('group' => 'cattempts'));
$mform->disabledIf('completionpass', 'completionusegrade', 'notchecked'); $mform->disabledIf('completionattemptsexhausted', 'completionpassgrade', 'notchecked');
$group[] = $mform->createElement('advcheckbox', 'completionattemptsexhausted', null, $items[] = 'completionattemptsexhausted';
get_string('completionattemptsexhausted', 'quiz'),
array('group' => 'cattempts'));
$mform->disabledIf('completionattemptsexhausted', 'completionpass', 'notchecked');
$mform->addGroup($group, 'completionpassgroup', get_string('completionpass', 'quiz'), ' &nbsp; ', false);
$mform->addHelpButton('completionpassgroup', 'completionpass', 'quiz');
$items[] = 'completionpassgroup';
$group = array(); $group = array();
$group[] = $mform->createElement('checkbox', 'completionminattemptsenabled', '', $group[] = $mform->createElement('checkbox', 'completionminattemptsenabled', '',
...@@ -648,7 +629,6 @@ class mod_quiz_mod_form extends moodleform_mod { ...@@ -648,7 +629,6 @@ class mod_quiz_mod_form extends moodleform_mod {
*/ */
public function completion_rule_enabled($data) { public function completion_rule_enabled($data) {
return !empty($data['completionattemptsexhausted']) || return !empty($data['completionattemptsexhausted']) ||
!empty($data['completionpass']) ||
!empty($data['completionminattemptsenabled']); !empty($data['completionminattemptsenabled']);
} }
......
...@@ -25,8 +25,8 @@ Feature: Set a quiz to be marked complete when the student uses all attempts all ...@@ -25,8 +25,8 @@ Feature: Set a quiz to be marked complete when the student uses all attempts all
| questioncategory | qtype | name | questiontext | | questioncategory | qtype | name | questiontext |
| Test questions | truefalse | First question | Answer the first question | | Test questions | truefalse | First question | Answer the first question |
And the following "activities" exist: And the following "activities" exist:
| activity | name | course | idnumber | attempts | gradepass | completion | completionusegrade | completionpass | completionattemptsexhausted | | activity | name | course | idnumber | attempts | gradepass | completion | completionusegrade | completionpassgrade | completionattemptsexhausted |
| quiz | Test quiz name | C1 | quiz1 | 2 | 5.00 | 2 | 1 | 1 | 1 | | quiz | Test quiz name | C1 | quiz1 | 2 | 5.00 | 2 | 1 | 1 | 1 |
And quiz "Test quiz name" contains the following questions: And quiz "Test quiz name" contains the following questions:
| question | page | | question | page |
| First question | 1 | | First question | 1 |
...@@ -37,7 +37,8 @@ Feature: Set a quiz to be marked complete when the student uses all attempts all ...@@ -37,7 +37,8 @@ Feature: Set a quiz to be marked complete when the student uses all attempts all
Scenario: student1 uses up both attempts without passing Scenario: student1 uses up both attempts without passing
When I log in as "student1" When I log in as "student1"
And I am on "Course 1" course homepage And I am on "Course 1" course homepage
And the "Receive a grade" completion condition of "Test quiz name" is displayed as "failed" And the "Receive a grade" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "failed"
And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo" And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo"
And I follow "Test quiz name" And I follow "Test quiz name"
And I press "Re-attempt quiz" And I press "Re-attempt quiz"
...@@ -45,10 +46,12 @@ Feature: Set a quiz to be marked complete when the student uses all attempts all ...@@ -45,10 +46,12 @@ Feature: Set a quiz to be marked complete when the student uses all attempts all
And I press "Finish attempt ..." And I press "Finish attempt ..."
And I press "Submit all and finish" And I press "Submit all and finish"
And I am on "Course 1" course homepage And I am on "Course 1" course homepage
Then the "Receive a grade" completion condition of "Test quiz name" is displayed as "failed" Then the "Receive a grade" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "failed"
And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "done" And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "done"
And I follow "Test quiz name" And I follow "Test quiz name"
And the "Receive a grade" completion condition of "Test quiz name" is displayed as "failed" And the "Receive a grade" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "failed"
And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "done" And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "done"
And I log out And I log out
And I log in as "teacher1" And I log in as "teacher1"
......
...@@ -25,8 +25,8 @@ Feature: Set a quiz to be marked complete when the student passes ...@@ -25,8 +25,8 @@ Feature: Set a quiz to be marked complete when the student passes
| questioncategory | qtype | name | questiontext | | questioncategory | qtype | name | questiontext |
| Test questions | truefalse | First question | Answer the first question | | Test questions | truefalse | First question | Answer the first question |
And the following "activities" exist: And the following "activities" exist:
| activity | name | course | idnumber | attempts | gradepass | completion | completionusegrade | completionpass | completionview | | activity | name | course | idnumber | attempts | gradepass | completion | completionusegrade | completionpassgrade | completionview |
| quiz | Test quiz name | C1 | quiz1 | 4 | 5.00 | 2 | 1 | 1 | 1 | | quiz | Test quiz name | C1 | quiz1 | 4 | 5.00 | 2 | 1 | 1 | 1 |
And quiz "Test quiz name" contains the following questions: And quiz "Test quiz name" contains the following questions:
| question | page | | question | page |
| First question | 1 | | First question | 1 |
...@@ -35,18 +35,18 @@ Feature: Set a quiz to be marked complete when the student passes ...@@ -35,18 +35,18 @@ Feature: Set a quiz to be marked complete when the student passes
When I log in as "student1" When I log in as "student1"
And I am on "Course 1" course homepage And I am on "Course 1" course homepage
And the "Receive a grade" completion condition of "Test quiz name" is displayed as "todo" And the "Receive a grade" completion condition of "Test quiz name" is displayed as "todo"
And the "Receive a pass grade" completion condition of "Test quiz name" is displayed as "todo" And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "todo"
And the "View" completion condition of "Test quiz name" is displayed as "todo" And the "View" completion condition of "Test quiz name" is displayed as "todo"
And user "student1" has attempted "Test quiz name" with responses: And user "student1" has attempted "Test quiz name" with responses:
| slot | response | | slot | response |
| 1 | True | | 1 | True |
And I follow "Test quiz name" And I follow "Test quiz name"
Then the "Receive a grade" completion condition of "Test quiz name" is displayed as "done" Then the "Receive a grade" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a pass grade" completion condition of "Test quiz name" is displayed as "done" And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "done"
And the "View" completion condition of "Test quiz name" is displayed as "done" And the "View" completion condition of "Test quiz name" is displayed as "done"
And I am on "Course 1" course homepage And I am on "Course 1" course homepage
And the "Receive a grade" completion condition of "Test quiz name" is displayed as "done" And the "Receive a grade" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a pass grade" completion condition of "Test quiz name" is displayed as "done" And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "done"
And the "View" completion condition of "Test quiz name" is displayed as "done" And the "View" completion condition of "Test quiz name" is displayed as "done"
And I log out And I log out
And I log in as "teacher1" And I log in as "teacher1"
......
...@@ -35,7 +35,7 @@ Feature: View activity completion in the quiz activity ...@@ -35,7 +35,7 @@ Feature: View activity completion in the quiz activity
| completion | 2 | | completion | 2 |
| completionview | 1 | | completionview | 1 |
| completionusegrade | 1 | | completionusegrade | 1 |
| completionpass | 1 | | completionpassgrade | 1 |
| completionattemptsexhausted | 1 | | completionattemptsexhausted | 1 |
| completionminattemptsenabled | 1 | | completionminattemptsenabled | 1 |
| completionminattempts | 1 | | completionminattempts | 1 |
...@@ -50,6 +50,7 @@ Feature: View activity completion in the quiz activity ...@@ -50,6 +50,7 @@ Feature: View activity completion in the quiz activity
And the "View" completion condition of "Test quiz name" is displayed as "done" And the "View" completion condition of "Test quiz name" is displayed as "done"
And the "Make attempts: 1" completion condition of "Test quiz name" is displayed as "todo" And the "Make attempts: 1" completion condition of "Test quiz name" is displayed as "todo"
And the "Receive a grade" completion condition of "Test quiz name" is displayed as "todo" And the "Receive a grade" completion condition of "Test quiz name" is displayed as "todo"
And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "todo"
And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo" And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo"
And user "student1" has attempted "Test quiz name" with responses: And user "student1" has attempted "Test quiz name" with responses:
| slot | response | | slot | response |
...@@ -58,7 +59,8 @@ Feature: View activity completion in the quiz activity ...@@ -58,7 +59,8 @@ Feature: View activity completion in the quiz activity
And I follow "Test quiz name" And I follow "Test quiz name"
And the "View" completion condition of "Test quiz name" is displayed as "done" And the "View" completion condition of "Test quiz name" is displayed as "done"
And the "Make attempts: 1" completion condition of "Test quiz name" is displayed as "done" And the "Make attempts: 1" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a grade" completion condition of "Test quiz name" is displayed as "failed" And the "Receive a grade" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "failed"
And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo" And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "todo"
And I press "Re-attempt quiz" And I press "Re-attempt quiz"
And I set the field "True" to "1" And I set the field "True" to "1"
...@@ -68,4 +70,5 @@ Feature: View activity completion in the quiz activity ...@@ -68,4 +70,5 @@ Feature: View activity completion in the quiz activity
And the "View" completion condition of "Test quiz name" is displayed as "done" And the "View" completion condition of "Test quiz name" is displayed as "done"
And the "Make attempts: 1" completion condition of "Test quiz name" is displayed as "done" And the "Make attempts: 1" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a grade" completion condition of "Test quiz name" is displayed as "done" And the "Receive a grade" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a passing grade" completion condition of "Test quiz name" is displayed as "done"
And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "done" And the "Receive a pass grade or complete all available attempts" completion condition of "Test quiz name" is displayed as "done"
...@@ -228,6 +228,7 @@ class mod_quiz_external_testcase extends externallib_advanced_testcase { ...@@ -228,6 +228,7 @@ class mod_quiz_external_testcase extends externallib_advanced_testcase {
$quiz1->groupingid = 0; $quiz1->groupingid = 0;
$quiz1->hasquestions = 0; $quiz1->hasquestions = 0;
$quiz1->hasfeedback = 0; $quiz1->hasfeedback = 0;
$quiz1->completionpass = 0;
$quiz1->autosaveperiod = get_config('quiz', 'autosaveperiod'); $quiz1->autosaveperiod = get_config('quiz', 'autosaveperiod');
$quiz1->introfiles = []; $quiz1->introfiles = [];
...@@ -239,6 +240,7 @@ class mod_quiz_external_testcase extends externallib_advanced_testcase { ...@@ -239,6 +240,7 @@ class mod_quiz_external_testcase extends externallib_advanced_testcase {
$quiz2->groupingid = 0; $quiz2->groupingid = 0;