MDL-79295 quiz: Add proper WS support for sequential nav.

This commit is contained in:
Juan Leyva
2024-01-26 10:24:16 +01:00
parent 810554ee83
commit 30598cf2a0
2 changed files with 46 additions and 30 deletions
+38 -26
View File
@@ -968,41 +968,18 @@ class mod_quiz_external extends external_api {
$qattempt = $attemptobj->get_question_attempt($slot);
$questiondef = $qattempt->get_question(true);
// Get response files (for questions like essay that allows attachments).
$responsefileareas = [];
foreach (question_bank::get_qtype($qtype)->response_file_areas() as $area) {
if ($files = $attemptobj->get_question_attempt($slot)->get_last_qt_files($area, $contextid)) {
$responsefileareas[$area]['area'] = $area;
$responsefileareas[$area]['files'] = [];
foreach ($files as $file) {
$responsefileareas[$area]['files'][] = [
'filename' => $file->get_filename(),
'fileurl' => $qattempt->get_response_file_url($file),
'filesize' => $file->get_filesize(),
'filepath' => $file->get_filepath(),
'mimetype' => $file->get_mimetype(),
'timemodified' => $file->get_timemodified(),
];
}
}
}
// Check display settings for question.
$settings = $questiondef->get_question_definition_for_external_rendering($qattempt, $displayoptions);
// Navigation information.
$question = [
'slot' => $slot,
'type' => $qtype,
'page' => $attemptobj->get_question_page($slot),
'questionnumber' => $attemptobj->get_question_number($slot),
'flagged' => $attemptobj->is_question_flagged($slot),
'html' => $attemptobj->render_question($slot, $review, $renderer) . $PAGE->requires->get_end_code(),
'responsefileareas' => $responsefileareas,
'sequencecheck' => $qattempt->get_sequence_check_count(),
'lastactiontime' => $qattempt->get_last_step()->get_timecreated(),
'hasautosavedstep' => $qattempt->has_autosaved_step(),
'settings' => !empty($settings) ? json_encode($settings) : null,
];
if ($question['questionnumber'] === (string) (int) $question['questionnumber']) {
@@ -1023,9 +1000,44 @@ class mod_quiz_external extends external_api {
if ($displayoptions->marks >= question_display_options::MARK_AND_MAX) {
$question['mark'] = $attemptobj->get_question_mark($slot);
}
if ($attemptobj->check_page_access($attemptobj->get_question_page($slot), false)) {
$questions[] = $question;
// Check access. This is needed especially when sequential navigation is enforced. To prevent the student see "future" questions.
$haveaccess = $attemptobj->check_page_access($attemptobj->get_question_page($slot), false);
if (!$haveaccess) {
$question['type'] = '';
$question['html'] = '';
}
// For visited pages/questions it is ok to keep data the user already saw.
$questionalreadyseen = $attemptobj->get_currentpage() >= $attemptobj->get_question_page($slot);
// Information when only the user has access to the question at any moment (free navigation) or already seen.
if ($haveaccess || $questionalreadyseen) {
// Get response files (for questions like essay that allows attachments).
$responsefileareas = [];
foreach (question_bank::get_qtype($qtype)->response_file_areas() as $area) {
if ($files = $attemptobj->get_question_attempt($slot)->get_last_qt_files($area, $contextid)) {
$responsefileareas[$area]['area'] = $area;
$responsefileareas[$area]['files'] = [];
foreach ($files as $file) {
$responsefileareas[$area]['files'][] = [
'filename' => $file->get_filename(),
'fileurl' => $qattempt->get_response_file_url($file),
'filesize' => $file->get_filesize(),
'filepath' => $file->get_filepath(),
'mimetype' => $file->get_mimetype(),
'timemodified' => $file->get_timemodified(),
];
}
}
}
$question['type'] = $qtype;
$question['html'] = $attemptobj->render_question($slot, $review, $renderer) . $PAGE->requires->get_end_code();
$question['responsefileareas'] = $responsefileareas;
$question['settings'] = !empty($settings) ? json_encode($settings) : null;
}
$questions[] = $question;
}
return $questions;
}
+8 -4
View File
@@ -2074,17 +2074,20 @@ class external_test extends externallib_advanced_testcase {
}
/**
* Test that a sequential navigation quiz is not allowing to see questions in advance for a student
* Test that a sequential navigation quiz is not allowing to see questions content in advance for a student.
*/
public function test_sequential_navigation_attempt_summary() {
// Test user with full capabilities.
$quiz = $this->prepare_sequential_quiz();
$attemptobj = $this->create_quiz_attempt_object($quiz);
$this->setUser($this->student);
// Check that we do not return other questions than the one currently viewed.
// Check that we do not return content from other questions except than the ones currently viewed.
$result = mod_quiz_external::get_attempt_summary($attemptobj->get_attemptid());
$this->assertCount(1, $result['questions']);
$this->assertStringContainsString('Question (1)', $result['questions'][0]['html']);
$this->assertStringContainsString('Question (1)', $result['questions'][0]['html']); // Current question.
$this->assertEmpty($result['questions'][1]['html']); // Next question.
$this->assertEmpty($result['questions'][2]['html']); // And more.
$this->assertEmpty($result['questions'][3]['html']); // And more.
$this->assertEmpty($result['questions'][4]['html']); // And more.
}
/**
@@ -2137,6 +2140,7 @@ class external_test extends externallib_advanced_testcase {
$data = [
'course' => $this->course->id,
'sumgrades' => 2,
'questionsperpage' => 1,
'preferredbehaviour' => 'deferredfeedback',
'navmethod' => QUIZ_NAVMETHOD_SEQ
];