MDL-72493 mod_quiz: Use question cache when starting attempt.

Replaced custom loading of data and then question object
creation using internal question_bank functionality with
question_bank::load_question.

Removed the call $quizobj->load_questions as it is
redundant.
This commit is contained in:
Darren Cocco 2021-09-08 10:38:11 +10:00 committed by Mihail Geshoski
parent ef93325f27
commit 0f5a9e7680
8 changed files with 20 additions and 16 deletions

View File

@ -2001,7 +2001,6 @@ class mod_quiz_external extends external_api {
$quizobj = quiz_settings::create($cm->instance, $USER->id);
$quizobj->preload_questions();
$quizobj->load_questions();
// Question types used.
$result = [];

View File

@ -338,9 +338,10 @@ class quiz_settings {
* Get some of the question in this quiz.
*
* @param array|null $questionids question ids of the questions to load. null for all.
* @param bool $requirequestionfullyloaded Whether to require that a particular question is fully loaded.
* @return stdClass[] the question data objects.
*/
public function get_questions($questionids = null) {
public function get_questions(?array $questionids = null, bool $requirequestionfullyloaded = true) {
if (is_null($questionids)) {
$questionids = array_keys($this->questions);
}
@ -350,7 +351,9 @@ class quiz_settings {
throw new moodle_exception('cannotstartmissingquestion', 'quiz', $this->view_url());
}
$questions[$id] = $this->questions[$id];
$this->ensure_question_loaded($id);
if ($requirequestionfullyloaded) {
$this->ensure_question_loaded($id);
}
}
return $questions;
}
@ -561,7 +564,7 @@ class quiz_settings {
// To control if we need to look in categories for questions.
$qcategories = [];
foreach ($this->get_questions() as $questiondata) {
foreach ($this->get_questions(null, false) as $questiondata) {
if ($questiondata->status == question_version_status::QUESTION_STATUS_DRAFT) {
// Skip questions where all versions are draft.
continue;

View File

@ -1943,8 +1943,7 @@ function quiz_check_updates_since(cm_info $cm, $from, $filter = []) {
$updates->questions = (object) ['updated' => false];
$quizobj = quiz_settings::create($cm->instance, $USER->id);
$quizobj->preload_questions();
$quizobj->load_questions();
$questionids = array_keys($quizobj->get_questions());
$questionids = array_keys($quizobj->get_questions(null, false));
if (!empty($questionids)) {
list($questionsql, $params) = $DB->get_in_or_equal($questionids, SQL_PARAMS_NAMED);
$select = 'id ' . $questionsql . ' AND (timemodified > :time1 OR timecreated > :time2)';

View File

@ -167,9 +167,8 @@ function quiz_start_new_attempt($quizobj, $quba, $attempt, $attemptnumber, $time
$qubaids = new \mod_quiz\question\qubaids_for_users_attempts(
$quizobj->get_quizid(), $attempt->userid);
// Fully load all the questions in this quiz.
// Partially load all the questions in this quiz.
$quizobj->preload_questions();
$quizobj->load_questions();
// First load all the non-random questions.
$randomfound = false;
@ -177,7 +176,7 @@ function quiz_start_new_attempt($quizobj, $quba, $attempt, $attemptnumber, $time
$questions = [];
$maxmark = [];
$page = [];
foreach ($quizobj->get_questions() as $questiondata) {
foreach ($quizobj->get_questions(null, false) as $questiondata) {
$slot += 1;
$maxmark[$slot] = $questiondata->maxmark;
$page[$slot] = $questiondata->page;
@ -188,10 +187,7 @@ function quiz_start_new_attempt($quizobj, $quba, $attempt, $attemptnumber, $time
$randomfound = true;
continue;
}
if (!$quizobj->get_quiz()->shuffleanswers) {
$questiondata->options->shuffleanswers = false;
}
$questions[$slot] = question_bank::make_question($questiondata);
$questions[$slot] = question_bank::load_question($questiondata->questionid, $quizobj->get_quiz()->shuffleanswers);
}
// Then find a question to go in place of each random question.
@ -207,7 +203,7 @@ function quiz_start_new_attempt($quizobj, $quba, $attempt, $attemptnumber, $time
}
$randomloader = new \core_question\local\bank\random_question_loader($qubaids, $usedquestionids);
foreach ($quizobj->get_questions() as $questiondata) {
foreach ($quizobj->get_questions(null, false) as $questiondata) {
$slot += 1;
if ($questiondata->qtype != 'random') {
continue;

View File

@ -494,9 +494,10 @@ class attempt_test extends \advanced_testcase {
$attempt = quiz_create_attempt($quizobj, 1, false, time(), false, $student1->id);
$attempt = quiz_start_new_attempt($quizobj, $quba, $attempt, 1, time());
$attempt = quiz_attempt_save_started($quizobj, $quba, $attempt);
$DB->set_field('question_versions', 'status', question_version_status::QUESTION_STATUS_DRAFT,
['questionid' => $question->id]);
// We need to reset the cache since the question has been edited by changing its status to draft.
\question_bank::notify_question_edited($question->id);
$quizobj = quiz_settings::create($quiz->id);
$quba = question_engine::make_questions_usage_by_activity('mod_quiz', $quizobj->get_context());
$quba->set_preferred_behaviour($quizobj->get_quiz()->preferredbehaviour);

View File

@ -1,5 +1,10 @@
This files describes API changes in the quiz code.
=== 4.3 ===
* The method get_questions() has a new parameter 'requirequestionfullyloaded' which can be used to instruct whether the
questions should be fully loaded or not.
=== 4.2 ===
* For the three quiz web services: mod_quiz_get_attempt_data, mod_quiz_get_attempt_summary and

View File

@ -63,7 +63,7 @@ class question_usage_test extends \advanced_testcase {
$question = $questiongenerator->create_question('shortanswer', null, ['category' => $cat->id]);
quiz_add_quiz_question($question->id, $quiz, $page);
$questions [] = $question;
$questions[] = $question;
}
$timenow = time();

View File

@ -650,6 +650,7 @@ class question_finder implements cache_data_source {
/* See cache_data_source::load_many_for_cache. */
public function load_many_for_cache(array $questionids) {
global $DB;
list($idcondition, $params) = $DB->get_in_or_equal($questionids);
$sql = 'SELECT q.id, qc.id as category, q.parent, q.name, q.questiontext, q.questiontextformat,
q.generalfeedback, q.generalfeedbackformat, q.defaultmark, q.penalty, q.qtype,