From cc880cabf565c141904c8bb264586b478b4afc7a Mon Sep 17 00:00:00 2001 From: mkassaei Date: Tue, 9 May 2023 11:08:01 +0100 Subject: [PATCH] MDL-77564 Quiz display options: Hide or show the grade information Allow settings to show Max marks and Marks, Max marks only, or hide the grade information completely. --- .../backup/moodle2/backup_quiz_stepslib.php | 2 +- .../backup/moodle2/restore_quiz_stepslib.php | 8 +++ mod/quiz/classes/admin/review_setting.php | 1 + mod/quiz/classes/external.php | 7 +- mod/quiz/classes/question/display_options.php | 4 +- mod/quiz/db/install.xml | 15 +++-- mod/quiz/db/upgrade.php | 15 +++++ mod/quiz/lang/en/quiz.php | 9 +++ mod/quiz/lib.php | 1 + mod/quiz/mod_form.php | 2 + .../behat/attempt_review_options.feature | 64 +++++++++++++++++++ .../settings_form_fields_disableif.feature | 6 ++ mod/quiz/tests/custom_completion_test.php | 1 + mod/quiz/tests/external/external_test.php | 2 +- mod/quiz/tests/generator/lib.php | 4 ++ .../tests/question/display_options_test.php | 8 ++- mod/quiz/version.php | 2 +- 17 files changed, 135 insertions(+), 16 deletions(-) create mode 100644 mod/quiz/tests/behat/attempt_review_options.feature diff --git a/mod/quiz/backup/moodle2/backup_quiz_stepslib.php b/mod/quiz/backup/moodle2/backup_quiz_stepslib.php index a411cfd586d..151cb7de9c6 100644 --- a/mod/quiz/backup/moodle2/backup_quiz_stepslib.php +++ b/mod/quiz/backup/moodle2/backup_quiz_stepslib.php @@ -34,7 +34,7 @@ class backup_quiz_activity_structure_step extends backup_questions_activity_stru 'name', 'intro', 'introformat', 'timeopen', 'timeclose', 'timelimit', 'overduehandling', 'graceperiod', 'preferredbehaviour', 'canredoquestions', 'attempts_number', 'attemptonlast', 'grademethod', 'decimalpoints', 'questiondecimalpoints', - 'reviewattempt', 'reviewcorrectness', 'reviewmarks', + 'reviewattempt', 'reviewcorrectness', 'reviewmaxmarks', 'reviewmarks', 'reviewspecificfeedback', 'reviewgeneralfeedback', 'reviewrightanswer', 'reviewoverallfeedback', 'questionsperpage', 'navmethod', 'shuffleanswers', diff --git a/mod/quiz/backup/moodle2/restore_quiz_stepslib.php b/mod/quiz/backup/moodle2/restore_quiz_stepslib.php index 5709815c788..d88f078f91c 100644 --- a/mod/quiz/backup/moodle2/restore_quiz_stepslib.php +++ b/mod/quiz/backup/moodle2/restore_quiz_stepslib.php @@ -184,6 +184,14 @@ class restore_quiz_activity_structure_step extends restore_questions_activity_st ($oldreview & QUIZ_OLD_CLOSED & QUIZ_OLD_SCORES ? display_options::AFTER_CLOSE : 0); + if (!isset($data->reviewmaxmarks)) { + $data->reviewmaxmarks = + display_options::DURING | + display_options::IMMEDIATELY_AFTER | + display_options::LATER_WHILE_OPEN | + display_options::AFTER_CLOSE; + } + $data->reviewmarks = display_options::DURING | ($oldreview & QUIZ_OLD_IMMEDIATELY & QUIZ_OLD_SCORES ? diff --git a/mod/quiz/classes/admin/review_setting.php b/mod/quiz/classes/admin/review_setting.php index d22e2e108b9..f9a054cf002 100644 --- a/mod/quiz/classes/admin/review_setting.php +++ b/mod/quiz/classes/admin/review_setting.php @@ -63,6 +63,7 @@ class review_setting extends \admin_setting { return [ 'attempt' => get_string('theattempt', 'quiz'), 'correctness' => get_string('whethercorrect', 'question'), + 'maxmarks' => get_string('maxmarks', 'quiz'), 'marks' => get_string('marks', 'question'), 'specificfeedback' => get_string('specificfeedback', 'question'), 'generalfeedback' => get_string('generalfeedback', 'question'), diff --git a/mod/quiz/classes/external.php b/mod/quiz/classes/external.php index 8cae72c1ce3..d5b291f63e5 100644 --- a/mod/quiz/classes/external.php +++ b/mod/quiz/classes/external.php @@ -131,7 +131,7 @@ class mod_quiz_external extends external_api { $quizdetails['hasquestions'] = (int) $quizobj->has_questions(); $quizdetails['autosaveperiod'] = get_config('quiz', 'autosaveperiod'); - $additionalfields = ['attemptonlast', 'reviewattempt', 'reviewcorrectness', 'reviewmarks', + $additionalfields = ['attemptonlast', 'reviewattempt', 'reviewcorrectness', 'reviewmaxmarks', 'reviewmarks', 'reviewspecificfeedback', 'reviewgeneralfeedback', 'reviewrightanswer', 'reviewoverallfeedback', 'questionsperpage', 'navmethod', 'browsersecurity', 'delay1', 'delay2', 'showuserpicture', 'showblocks', @@ -208,8 +208,9 @@ class mod_quiz_external extends external_api { \mod_quiz\question\display_options class. It is formed by ORing together the constants defined there.', VALUE_OPTIONAL), 'reviewcorrectness' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz - attempts at various times. - A bit field, like reviewattempt.', VALUE_OPTIONAL), + attempts at various times.A bit field, like reviewattempt.', VALUE_OPTIONAL), + 'reviewmaxmarks' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz + attempts at various times. A bit field, like reviewattempt.', VALUE_OPTIONAL), 'reviewmarks' => new external_value(PARAM_INT, 'Whether users are allowed to review their quiz attempts at various times. A bit field, like reviewattempt.', VALUE_OPTIONAL), diff --git a/mod/quiz/classes/question/display_options.php b/mod/quiz/classes/question/display_options.php index 1e6d5d34a0a..b9904ff2796 100644 --- a/mod/quiz/classes/question/display_options.php +++ b/mod/quiz/classes/question/display_options.php @@ -72,8 +72,8 @@ class display_options extends \question_display_options { $options->attempt = self::extract($quiz->reviewattempt, $when, true, false); $options->correctness = self::extract($quiz->reviewcorrectness, $when); - $options->marks = self::extract($quiz->reviewmarks, $when, - self::MARK_AND_MAX, self::MAX_ONLY); + $options->marks = self::extract($quiz->reviewmaxmarks, $when, + self::extract($quiz->reviewmarks, $when, self::MARK_AND_MAX, self::MAX_ONLY), self::HIDDEN); $options->feedback = self::extract($quiz->reviewspecificfeedback, $when); $options->generalfeedback = self::extract($quiz->reviewgeneralfeedback, $when); $options->rightanswer = self::extract($quiz->reviewrightanswer, $when); diff --git a/mod/quiz/db/install.xml b/mod/quiz/db/install.xml index a5e9f2474e0..0f78dc049a0 100644 --- a/mod/quiz/db/install.xml +++ b/mod/quiz/db/install.xml @@ -19,17 +19,18 @@ - + - - - - - - + + + + + + + diff --git a/mod/quiz/db/upgrade.php b/mod/quiz/db/upgrade.php index 02be52bd761..df41e5e297b 100644 --- a/mod/quiz/db/upgrade.php +++ b/mod/quiz/db/upgrade.php @@ -179,5 +179,20 @@ function xmldb_quiz_upgrade($oldversion) { // Automatically generated Moodle v4.2.0 release upgrade line. // Put any upgrade step following this. + if ($oldversion < 2023042401) { + + // Define field reviewmaxmarks to be added to quiz. + $table = new xmldb_table('quiz'); + $field = new xmldb_field('reviewmaxmarks', XMLDB_TYPE_INTEGER, '6', null, XMLDB_NOTNULL, null, '0', 'reviewcorrectness'); + + // Conditionally launch add field reviewmaxmarks. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Quiz savepoint reached. + upgrade_mod_savepoint(true, 2023042401, 'quiz'); + } + return true; } diff --git a/mod/quiz/lang/en/quiz.php b/mod/quiz/lang/en/quiz.php index e5c24a60eab..98f3f531fda 100644 --- a/mod/quiz/lang/en/quiz.php +++ b/mod/quiz/lang/en/quiz.php @@ -532,6 +532,15 @@ $string['messageprovider:attempt_grading_complete'] = 'Notification that your at $string['messageprovider:submission'] = 'Notification of your students\' quiz submissions'; $string['max'] = 'Max'; $string['maxmark'] = 'Maximum mark'; +$string['maxmarks'] = 'Max Marks'; +$string['maxmarks_help'] = 'Max marks determines whether the grade information are hidden or how it is displayed: + +* To hide the grade information completely, do not tick this checkbox (Marks checkbox is disabled automatically). + +* To show Max marks only: tick this checkbox and not the Marks checkbox. + +* To show both Max marks and Marks, tick this checkbox as well as the Marks checkbox.'; + $string['min'] = 'Min'; $string['minutes'] = 'Minutes'; $string['missingcorrectanswer'] = 'Correct answer must be specified'; diff --git a/mod/quiz/lib.php b/mod/quiz/lib.php index 08841dd0730..f64b5f147d5 100644 --- a/mod/quiz/lib.php +++ b/mod/quiz/lib.php @@ -1117,6 +1117,7 @@ function quiz_process_options($quiz) { // Combing the individual settings into the review columns. $quiz->reviewattempt = quiz_review_option_form_to_db($quiz, 'attempt'); $quiz->reviewcorrectness = quiz_review_option_form_to_db($quiz, 'correctness'); + $quiz->reviewmaxmarks = quiz_review_option_form_to_db($quiz, 'maxmarks'); $quiz->reviewmarks = quiz_review_option_form_to_db($quiz, 'marks'); $quiz->reviewspecificfeedback = quiz_review_option_form_to_db($quiz, 'specificfeedback'); $quiz->reviewgeneralfeedback = quiz_review_option_form_to_db($quiz, 'generalfeedback'); diff --git a/mod/quiz/mod_form.php b/mod/quiz/mod_form.php index 44cff553ebd..cf91026c424 100644 --- a/mod/quiz/mod_form.php +++ b/mod/quiz/mod_form.php @@ -54,6 +54,7 @@ class mod_quiz_mod_form extends moodleform_mod { self::$reviewfields = [ 'attempt' => ['theattempt', 'quiz'], 'correctness' => ['whethercorrect', 'question'], + 'maxmarks' => ['maxmarks', 'quiz'], 'marks' => ['marks', 'quiz'], 'specificfeedback' => ['specificfeedback', 'question'], 'generalfeedback' => ['generalfeedback', 'question'], @@ -403,6 +404,7 @@ class mod_quiz_mod_form extends moodleform_mod { } } + $mform->disabledIf('marks' . $whenname, 'maxmarks' . $whenname); if ($whenname != 'during') { $mform->disabledIf('correctness' . $whenname, 'attempt' . $whenname); $mform->disabledIf('specificfeedback' . $whenname, 'attempt' . $whenname); diff --git a/mod/quiz/tests/behat/attempt_review_options.feature b/mod/quiz/tests/behat/attempt_review_options.feature new file mode 100644 index 00000000000..d33d45fb1d9 --- /dev/null +++ b/mod/quiz/tests/behat/attempt_review_options.feature @@ -0,0 +1,64 @@ +@mod @mod_quiz +Feature: Allow settings to show Max marks and Marks, Max marks only, or hide the grade information completely. + As a teacher + In order to decide how grade review options are displayed on questions in a quiz review page + I need to be able to set the grade review options for a quiz to to show Max and Marks, Max only, or hide the grade information. + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | student1 | Student | One | student1@example.com | + | teacher | Teacher | One | teacher@example.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher | C1 | editingteacher | + | student1 | C1 | student | + And the following "question categories" exist: + | contextlevel | reference | name | + | Course | C1 | Test questions | + And the following "questions" exist: + | questioncategory | qtype | name | questiontext | + | Test questions | truefalse | TF1 | First question | + And the following "activities" exist: + | activity | name | intro | course | idnumber | maxmarksduring | marksduring | maxmarksimmediately | marksimmediately | preferredbehaviour | + | quiz | Quiz 1 | Quiz 1 test | C1 | quiz1 | 1 | 1 | 1 | 1 | immediatefeedback | + | quiz | Quiz 2 | Quiz 2 test | C1 | quiz2 | 0 | 0 | 1 | 1 | immediatefeedback | + And quiz "Quiz 1" contains the following questions: + | question | page | maxmark | + | TF1 | 1 | 2.00 | + And quiz "Quiz 2" contains the following questions: + | question | page | maxmark | + | TF1 | 1 | 2.00 | + + @javascript + Scenario: Show max marks and marks during and immediately after the attempt. + Given I am on the "Quiz 1" "quiz activity" page logged in as "student1" + And I click on "Attempt quiz" "button" + And I should see "Question 1" in the ".info" "css_element" + And I should see "Not complete" in the ".info" "css_element" + And I should see "Marked out of 2.00" in the ".info" "css_element" + And I set the field "True" to "1" + And I press "Finish attempt ..." + And I press "Submit all and finish" + And I click on "Submit all and finish" "button" in the "Submit all your answers and finish?" "dialogue" + Then I should see "Finished" in the "State" "table_row" + And I should see "Question 1" in the ".info" "css_element" + And I should see "Correct" in the ".info" "css_element" + And I should see "Mark 2.00 out of 2.00" in the ".info" "css_element" + + And I am on the "Quiz 2" "quiz activity" page + And I click on "Attempt quiz" "button" + And I should see "Question 1" in the ".info" "css_element" + And I should see "Not complete" in the ".info" "css_element" + And I should not see "Marked out of 2.00" in the ".info" "css_element" + And I set the field "True" to "1" + And I press "Finish attempt ..." + And I press "Submit all and finish" + And I click on "Submit all and finish" "button" in the "Submit all your answers and finish?" "dialogue" + And I should see "Finished" in the "State" "table_row" + And I should see "Question 1" in the ".info" "css_element" + And I should see "Correct" in the ".info" "css_element" + And I should see "Mark 2.00 out of 2.00" in the ".info" "css_element" diff --git a/mod/quiz/tests/behat/settings_form_fields_disableif.feature b/mod/quiz/tests/behat/settings_form_fields_disableif.feature index 56bdfe89c3c..8062d3e0e56 100644 --- a/mod/quiz/tests/behat/settings_form_fields_disableif.feature +++ b/mod/quiz/tests/behat/settings_form_fields_disableif.feature @@ -102,6 +102,7 @@ Feature: Settings form fields disabled if not required And I set the field "Name" to "Test quiz" Then the "id_attemptclosed" "checkbox" should be disabled And the "id_correctnessclosed" "checkbox" should be disabled + And the "id_maxmarksclosed" "checkbox" should be disabled And the "id_marksclosed" "checkbox" should be disabled And the "id_specificfeedbackclosed" "checkbox" should be disabled And the "id_generalfeedbackclosed" "checkbox" should be disabled @@ -110,11 +111,16 @@ Feature: Settings form fields disabled if not required And I set the field "id_timeclose_enabled" to "1" And the "id_attemptclosed" "checkbox" should be enabled And the "id_correctnessclosed" "checkbox" should be enabled + And the "id_maxmarksclosed" "checkbox" should be enabled And the "id_marksclosed" "checkbox" should be enabled + And I set the field "id_maxmarksclosed" to "0" + And the "id_marksclosed" "checkbox" should be disabled And the "id_specificfeedbackclosed" "checkbox" should be enabled And the "id_generalfeedbackclosed" "checkbox" should be enabled And the "id_rightanswerclosed" "checkbox" should be enabled And the "id_overallfeedbackclosed" "checkbox" should be enabled + And I set the field "id_maxmarksduring" to "0" + And the "id_marksduring" "checkbox" should be disabled And I should not see "Repaginate now" @javascript diff --git a/mod/quiz/tests/custom_completion_test.php b/mod/quiz/tests/custom_completion_test.php index e1c61c2da00..5d8084d0066 100644 --- a/mod/quiz/tests/custom_completion_test.php +++ b/mod/quiz/tests/custom_completion_test.php @@ -485,6 +485,7 @@ class custom_completion_test extends advanced_testcase { $moduleinfo->modulename = 'quiz'; $moduleinfo->quizpassword = ''; $moduleinfo->cmidnumber = ''; + $moduleinfo->maxmarksopen = 1; $moduleinfo->marksopen = 1; $moduleinfo->visible = 1; $moduleinfo->visibleoncoursepage = 1; diff --git a/mod/quiz/tests/external/external_test.php b/mod/quiz/tests/external/external_test.php index 9c8cf01de62..9fc37410f38 100644 --- a/mod/quiz/tests/external/external_test.php +++ b/mod/quiz/tests/external/external_test.php @@ -246,7 +246,7 @@ class external_test extends externallib_advanced_testcase { 'timeopen', 'timeclose', 'grademethod', 'section', 'visible', 'groupmode', 'groupingid', 'attempts', 'timelimit', 'grademethod', 'decimalpoints', 'questiondecimalpoints', 'sumgrades', 'grade', 'preferredbehaviour', 'hasfeedback']; - $userswithaccessfields = ['attemptonlast', 'reviewattempt', 'reviewcorrectness', 'reviewmarks', + $userswithaccessfields = ['attemptonlast', 'reviewattempt', 'reviewcorrectness', 'reviewmaxmarks', 'reviewmarks', 'reviewspecificfeedback', 'reviewgeneralfeedback', 'reviewrightanswer', 'reviewoverallfeedback', 'questionsperpage', 'navmethod', 'browsersecurity', 'delay1', 'delay2', 'showuserpicture', 'showblocks', diff --git a/mod/quiz/tests/generator/lib.php b/mod/quiz/tests/generator/lib.php index 9e175f958cf..b5e50634dc5 100644 --- a/mod/quiz/tests/generator/lib.php +++ b/mod/quiz/tests/generator/lib.php @@ -45,6 +45,7 @@ class mod_quiz_generator extends testing_module_generator { 'questiondecimalpoints' => -1, 'attemptduring' => 1, 'correctnessduring' => 1, + 'maxmarksduring' => 1, 'marksduring' => 1, 'specificfeedbackduring' => 1, 'generalfeedbackduring' => 1, @@ -52,6 +53,7 @@ class mod_quiz_generator extends testing_module_generator { 'overallfeedbackduring' => 0, 'attemptimmediately' => 1, 'correctnessimmediately' => 1, + 'maxmarksimmediately' => 1, 'marksimmediately' => 1, 'specificfeedbackimmediately' => 1, 'generalfeedbackimmediately' => 1, @@ -59,6 +61,7 @@ class mod_quiz_generator extends testing_module_generator { 'overallfeedbackimmediately' => 1, 'attemptopen' => 1, 'correctnessopen' => 1, + 'maxmarksopen' => 1, 'marksopen' => 1, 'specificfeedbackopen' => 1, 'generalfeedbackopen' => 1, @@ -66,6 +69,7 @@ class mod_quiz_generator extends testing_module_generator { 'overallfeedbackopen' => 1, 'attemptclosed' => 1, 'correctnessclosed' => 1, + 'maxmarksclosed' => 1, 'marksclosed' => 1, 'specificfeedbackclosed' => 1, 'generalfeedbackclosed' => 1, diff --git a/mod/quiz/tests/question/display_options_test.php b/mod/quiz/tests/question/display_options_test.php index 135cbb80a63..21e245c8f06 100644 --- a/mod/quiz/tests/question/display_options_test.php +++ b/mod/quiz/tests/question/display_options_test.php @@ -37,7 +37,8 @@ class display_options_test extends \basic_testcase { $quiz->questiondecimalpoints = -1; $quiz->reviewattempt = 0x11110; $quiz->reviewcorrectness = 0x10000; - $quiz->reviewmarks = 0x01110; + $quiz->reviewmaxmarks = 0x10000; // Max marks is set. + $quiz->reviewmarks = 0x00000; // Marks is not set. $quiz->reviewspecificfeedback = 0x10000; $quiz->reviewgeneralfeedback = 0x01000; $quiz->reviewrightanswer = 0x00100; @@ -56,6 +57,8 @@ class display_options_test extends \basic_testcase { $this->assertEquals(2, $options->markdp); $quiz->questiondecimalpoints = 5; + $quiz->reviewmaxmarks = 0x11000; // Max marks is set. + $quiz->reviewmarks = 0x11000; // Marks is also set. $options = display_options::make_from_quiz($quiz, display_options::IMMEDIATELY_AFTER); @@ -67,9 +70,12 @@ class display_options_test extends \basic_testcase { $this->assertEquals(display_options::HIDDEN, $options->manualcomment); $this->assertEquals(5, $options->markdp); + $quiz->reviewmaxmarks = 0x00000; // Max marks is NOT set. + $quiz->reviewmarks = 0x00000; // Marks is also NOT set. $options = display_options::make_from_quiz($quiz, display_options::LATER_WHILE_OPEN); + $this->assertEquals(display_options::HIDDEN, $options->marks); $this->assertEquals(display_options::VISIBLE, $options->rightanswer); $this->assertEquals(display_options::HIDDEN, $options->generalfeedback); diff --git a/mod/quiz/version.php b/mod/quiz/version.php index 68935482667..8b24296204a 100644 --- a/mod/quiz/version.php +++ b/mod/quiz/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2023042400; +$plugin->version = 2023042401; $plugin->requires = 2023041800; $plugin->component = 'mod_quiz';