MDL-76897 quiz: move quiz_update_sumgrades into grade_calculator

This commit is contained in:
Tim Hunt
2023-02-24 16:14:51 +00:00
parent 086bbf3f89
commit dbd62aa94d
9 changed files with 91 additions and 61 deletions
+5 -5
View File
@@ -29,6 +29,7 @@ require_once($CFG->dirroot . '/mod/quiz/locallib.php');
require_once($CFG->dirroot . '/question/editlib.php');
use mod_quiz\form\add_random_form;
use mod_quiz\quiz_settings;
use qbank_managecategories\question_category_object;
list($thispageurl, $contexts, $cmid, $cm, $quiz, $pagevars) =
@@ -41,10 +42,9 @@ $addonpage = optional_param('addonpage', 0, PARAM_INT);
$category = optional_param('category', 0, PARAM_INT);
$mdlscrollto = optional_param('mdlscrollto', 0, PARAM_INT);
// Get the course object and related bits.
if (!$course = $DB->get_record('course', ['id' => $quiz->course])) {
throw new \moodle_exception('invalidcourseid');
}
$quizobj = quiz_settings::create($quiz->id);
$course = $quizobj->get_course();
// You need mod/quiz:manage in addition to question capabilities to access this page.
// You also need the moodle/question:useall capability somewhere.
require_capability('mod/quiz:manage', $contexts->lowest());
@@ -113,7 +113,7 @@ if ($data = $mform->get_data()) {
quiz_add_random_questions($quiz, $addonpage, $categoryid, $data->numbertoadd, $includesubcategories, $tagids);
quiz_delete_previews($quiz);
quiz_update_sumgrades($quiz);
$quizobj->get_grade_calculator()->recompute_quiz_sumgrades();
redirect($returnurl);
}
+33 -1
View File
@@ -51,5 +51,37 @@ class grade_calculator {
return new self($quizobj);
}
/**
* Update the sumgrades field of the quiz.
*
* This needs to be called whenever the grading structure of the quiz is changed.
* For example if a question is added or removed, or a question weight is changed.
*
* You should call {@see quiz_delete_previews()} before you call this function.
*/
public function recompute_quiz_sumgrades(): void {
global $DB;
$quiz = $this->quizobj->get_quiz();
// Update sumgrades in the database.
$DB->execute("
UPDATE {quiz}
SET sumgrades = COALESCE((
SELECT SUM(maxmark)
FROM {quiz_slots}
WHERE quizid = {quiz}.id
), 0)
WHERE id = ?
", [$quiz->id]);
// Update the value in memory.
$quiz->sumgrades = $DB->get_field('quiz', 'sumgrades', ['id' => $quiz->id]);
if ($quiz->sumgrades < 0.000005 && quiz_has_attempts($quiz->id)) {
// If the quiz has been attempted, and the sumgrades has been
// set to 0, then we must also set the maximum possible grade to 0, or
// we will get a divide by zero error.
quiz_set_grade(0, $quiz);
}
}
}
+17
View File
@@ -305,3 +305,20 @@ class moodle_quiz_exception extends moodle_exception {
parent::__construct($errorcode, 'quiz', $link, $a, $debuginfo);
}
}
/**
* Update the sumgrades field of the quiz. This needs to be called whenever
* the grading structure of the quiz is changed. For example if a question is
* added or removed, or a question weight is changed.
*
* You should call {@see quiz_delete_previews()} before you call this function.
*
* @param stdClass $quiz a quiz.
* @deprecated since Moodle 4.2. Please use grade_calculator::recompute_quiz_sumgrades.
* @todo MDL-76612 Final deprecation in Moodle 4.6
*/
function quiz_update_sumgrades($quiz) {
debugging('quiz_update_sumgrades is deprecated. ' .
'Please use a standard grade_calculator::recompute_quiz_sumgrades instead.', DEBUG_DEVELOPER);
quiz_settings::create($quiz->id)->get_grade_calculator()->recompute_quiz_sumgrades();
}
+15 -14
View File
@@ -51,22 +51,23 @@ $mdlscrollto = optional_param('mdlscrollto', '', PARAM_INT);
list($thispageurl, $contexts, $cmid, $cm, $quiz, $pagevars) =
question_edit_setup('editq', '/mod/quiz/edit.php', true);
$PAGE->set_url($thispageurl);
$PAGE->set_secondary_active_tab("mod_quiz_edit");
// You need mod/quiz:manage in addition to question capabilities to access this page.
require_capability('mod/quiz:manage', $contexts->lowest());
// Get the course object and related bits.
$course = get_course($quiz->course);
$quizobj = new quiz_settings($quiz, $cm, $course);
$structure = $quizobj->get_structure();
$gradecalculator = $quizobj->get_grade_calculator();
$defaultcategoryobj = question_make_default_categories($contexts->all());
$defaultcategory = $defaultcategoryobj->id . ',' . $defaultcategoryobj->contextid;
$quizhasattempts = quiz_has_attempts($quiz->id);
$PAGE->set_url($thispageurl);
$PAGE->set_secondary_active_tab("mod_quiz_edit");
// Get the course object and related bits.
$course = $DB->get_record('course', ['id' => $quiz->course], '*', MUST_EXIST);
$quizobj = new quiz_settings($quiz, $cm, $course);
$structure = $quizobj->get_structure();
// You need mod/quiz:manage in addition to question capabilities to access this page.
require_capability('mod/quiz:manage', $contexts->lowest());
// Process commands ============================================================.
// Get the list of question ids had their check-boxes ticked.
@@ -100,7 +101,7 @@ if (($addquestion = optional_param('addquestion', 0, PARAM_INT)) && confirm_sess
$addonpage = optional_param('addonpage', 0, PARAM_INT);
quiz_add_quiz_question($addquestion, $quiz, $addonpage);
quiz_delete_previews($quiz);
quiz_update_sumgrades($quiz);
$gradecalculator->recompute_quiz_sumgrades();
$thispageurl->param('lastchanged', $addquestion);
redirect($afteractionurl);
}
@@ -118,7 +119,7 @@ if (optional_param('add', false, PARAM_BOOL) && confirm_sesskey()) {
}
}
quiz_delete_previews($quiz);
quiz_update_sumgrades($quiz);
$gradecalculator->recompute_quiz_sumgrades();
redirect($afteractionurl);
}
@@ -140,7 +141,7 @@ if ((optional_param('addrandom', false, PARAM_BOOL)) && confirm_sesskey()) {
quiz_add_random_questions($quiz, $addonpage, $categoryid, $randomcount, $recurse);
quiz_delete_previews($quiz);
quiz_update_sumgrades($quiz);
$gradecalculator->recompute_quiz_sumgrades();
redirect($afteractionurl);
}
+8 -7
View File
@@ -54,13 +54,14 @@ $PAGE->set_url('/mod/quiz/edit-rest.php',
['quizid' => $quizid, 'class' => $class]);
require_sesskey();
$quiz = $DB->get_record('quiz', ['id' => $quizid], '*', MUST_EXIST);
$cm = get_coursemodule_from_instance('quiz', $quiz->id, $quiz->course);
$course = $DB->get_record('course', ['id' => $quiz->course], '*', MUST_EXIST);
$quizobj = quiz_settings::create($quizid);
$quiz = $quizobj->get_quiz();
$cm = $quizobj->get_cm();
$course = $quizobj->get_course();
require_login($course, false, $cm);
$quizobj = new quiz_settings($quiz, $cm, $course);
$structure = $quizobj->get_structure();
$gradecalculator = $quizobj->get_grade_calculator();
$modcontext = context_module::instance($cm->id);
echo $OUTPUT->header(); // Send headers.
@@ -131,7 +132,7 @@ switch($requestmethod) {
if ($structure->update_slot_maxmark($slot, $maxmark)) {
// Grade has really changed.
quiz_delete_previews($quiz);
quiz_update_sumgrades($quiz);
$gradecalculator->recompute_quiz_sumgrades();
quiz_update_all_attempt_sumgrades($quiz);
quiz_update_all_final_grades($quiz);
quiz_update_grades($quiz, 0, true);
@@ -163,7 +164,7 @@ switch($requestmethod) {
}
}
quiz_delete_previews($quiz);
quiz_update_sumgrades($quiz);
$gradecalculator->recompute_quiz_sumgrades();
$result = ['newsummarks' => quiz_format_grade($quiz, $quiz->sumgrades),
'deleted' => true, 'newnumquestions' => $structure->get_question_count()];
@@ -203,7 +204,7 @@ switch($requestmethod) {
}
$structure->remove_slot($slot->slot);
quiz_delete_previews($quiz);
quiz_update_sumgrades($quiz);
$gradecalculator->recompute_quiz_sumgrades();
$result = ['newsummarks' => quiz_format_grade($quiz, $quiz->sumgrades),
'deleted' => true, 'newnumquestions' => $structure->get_question_count()];
break;
-30
View File
@@ -627,36 +627,6 @@ function quiz_has_feedback($quiz) {
return $cache[$quiz->id];
}
/**
* Update the sumgrades field of the quiz. This needs to be called whenever
* the grading structure of the quiz is changed. For example if a question is
* added or removed, or a question weight is changed.
*
* You should call {@link quiz_delete_previews()} before you call this function.
*
* @param stdClass $quiz a quiz.
*/
function quiz_update_sumgrades($quiz) {
global $DB;
$sql = 'UPDATE {quiz}
SET sumgrades = COALESCE((
SELECT SUM(maxmark)
FROM {quiz_slots}
WHERE quizid = {quiz}.id
), 0)
WHERE id = ?';
$DB->execute($sql, [$quiz->id]);
$quiz->sumgrades = $DB->get_field('quiz', 'sumgrades', ['id' => $quiz->id]);
if ($quiz->sumgrades < 0.000005 && quiz_has_attempts($quiz->id)) {
// If the quiz has been attempted, and the sumgrades has been
// set to 0, then we must also set the maximum possible grade to 0, or
// we will get a divide by zero error.
quiz_set_grade(0, $quiz);
}
}
/**
* Update the sumgrades field of the attempts at a quiz.
*
+2 -1
View File
@@ -175,8 +175,9 @@ class attempt_walkthrough_test extends \advanced_testcase {
$saq = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
// Add them to the quiz.
$quizobj = quiz_settings::create($quiz->id);
quiz_add_quiz_question($saq->id, $quiz, 0, 1);
quiz_update_sumgrades($quiz);
$quizobj->get_grade_calculator()->recompute_quiz_sumgrades();
return $quiz;
}
+3 -1
View File
@@ -32,6 +32,7 @@ use Behat\Gherkin\Node\TableNode as TableNode;
use Behat\Mink\Exception\ExpectationException as ExpectationException;
use mod_quiz\quiz_attempt;
use mod_quiz\quiz_settings;
/**
* Steps definitions related to mod_quiz.
@@ -307,7 +308,8 @@ class behat_mod_quiz extends behat_question_base {
}
}
quiz_update_sumgrades($quiz);
$quizobj = quiz_settings::create($quiz->id);
$quizobj->get_grade_calculator()->recompute_quiz_sumgrades();
}
/**
+8 -2
View File
@@ -4,9 +4,9 @@ This files describes API changes in the quiz code.
* The methods in the quiz_settings class which return a URL now all return a moodle_url. Previously
some returns a moodle_url and others aa string.
* The method quiz_settings::confirm_start_attempt_message, which was deprecated in Moodle 3.1, is now completely removed.
* The field view_page::$startattemptwarning, which was deprecated in Moodle 3.1, is now completely removed.
* 'firstslotid' value is not used in section_shuffle_updated event anymore.
* The quiz has a lot of old classes in lib.php files. These have now been moved into the classes folder,
and so are now in namespaces. Because of Moodle's class renaming support, your code should continue
working, but output deprecated warnings, so you probably want to update. This should mostly be
@@ -77,11 +77,17 @@ This files describes API changes in the quiz code.
- mod/quiz/renderer.php - actually, no debugging ouput for this one because of how renderer factories work.
- mod/quiz/attemptlib.php
* Various functions related to calculating grades have moved into a new class mod_quiz\grade_calculator.
You get that using $quizobj->get_grade_calculator(), then the following old functions have become these new methods.
- recompute_quiz_sumgrades ->
* Final deprecation (complete removal) of the following functions which were deprecated long ago:
- quiz_groups_member_added_handler - deprecated since 2.6
- quiz_groups_member_removed_handler - deprecated since 2.6
- quiz_groups_group_deleted_handler - deprecated since 2.6
- quiz_groups_members_removed_handler - deprecated since 2.6
- The method quiz_settings::confirm_start_attempt_message - deprecated in Moodle 3.1
- The field view_page::$startattemptwarning - deprecated in Moodle 3.1
- attempts_report::load_relevant_students - deprecated since 3.2
- quiz_statistics_graph_get_new_colour - deprecated since 3.2
- The file mod/quiz/report/overview/overviewgraph.php - deprecated since 3.2