MDL-76897 quiz: move quiz_update_sumgrades into grade_calculator
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user