Skip to content

Commit

Permalink
MDL-74543 quiz: correctly record time when overdue attempt submitted
Browse files Browse the repository at this point in the history
  • Loading branch information
timhunt committed May 3, 2022
1 parent 81e5d42 commit a0297df
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
10 changes: 9 additions & 1 deletion mod/quiz/attemptlib.php
Expand Up @@ -2469,7 +2469,15 @@ public function process_attempt($timenow, $finishattempt, $timeup, $thispage) {
if ($becomingabandoned) {
$this->process_abandon($timenow, true);
} else {
$this->process_finish($timenow, !$toolate, $toolate ? $timeclose : $timenow, true);
if (!$toolate || $this->get_quiz()->overduehandling == 'graceperiod') {
// Normally, we record the accurate finish time when the student is online.
$finishtime = $timenow;
} else {
// But, if there is no grade period, and the final responses were too
// late to be processed, record the close time, to reduce confusion.
$finishtime = $timeclose;
}
$this->process_finish($timenow, !$toolate, $finishtime, true);
}

} catch (question_out_of_sequence_exception $e) {
Expand Down
59 changes: 59 additions & 0 deletions mod/quiz/tests/attempt_walkthrough_test.php
Expand Up @@ -119,6 +119,65 @@ public function test_quiz_attempt_walkthrough() {
$this->assertEquals(100, $gradebookgrade->grade);
}

public function test_quiz_attempt_walkthrough_submit_time_recorded_correctly_when_overdue() {
global $SITE;

$this->resetAfterTest();

// Make a quiz.
$timeclose = time() + HOURSECS;
$quizgenerator = $this->getDataGenerator()->get_plugin_generator('mod_quiz');

$quiz = $quizgenerator->create_instance(
['course' => $SITE->id, 'timeclose' => $timeclose,
'overduehandling' => 'graceperiod', 'graceperiod' => HOURSECS]);

// Create a question.
$questiongenerator = $this->getDataGenerator()->get_plugin_generator('core_question');
$cat = $questiongenerator->create_question_category();
$saq = $questiongenerator->create_question('shortanswer', null, array('category' => $cat->id));

// Add them to the quiz.
quiz_add_quiz_question($saq->id, $quiz, 0, 1);
quiz_update_sumgrades($quiz);

// Make a user to do the quiz.
$user = $this->getDataGenerator()->create_user();
$this->setUser($user);
$quizobj = quiz::create($quiz->id, $user->id);

// Start the attempt.
$attempt = quiz_prepare_and_start_new_attempt($quizobj, 1, null);

// Process some responses from the student.
$attemptobj = quiz_attempt::create($attempt->id);
$attemptobj->process_submitted_actions($timeclose - 30 * MINSECS, false, [1 => ['answer' => 'frog']]);

// Attempt goes overdue (e.g. if cron ran).
$attemptobj = quiz_attempt::create($attempt->id);
$attemptobj->process_going_overdue($timeclose + 2 * get_config('quiz', 'graceperiodmin'), false);

// Verify the attempt state.
$attemptobj = quiz_attempt::create($attempt->id);
$this->assertEquals(1, $attemptobj->get_attempt_number());
$this->assertEquals(false, $attemptobj->is_finished());
$this->assertEquals(0, $attemptobj->get_submitted_date());
$this->assertEquals($user->id, $attemptobj->get_userid());
$this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());

// Student submits the attempt during the grace period.
$attemptobj = quiz_attempt::create($attempt->id);
$attemptobj->process_attempt($timeclose + 30 * MINSECS, true, false, 1);

// Verify the attempt state.
$attemptobj = quiz_attempt::create($attempt->id);
$this->assertEquals(1, $attemptobj->get_attempt_number());
$this->assertEquals(true, $attemptobj->is_finished());
$this->assertEquals($timeclose + 30 * MINSECS, $attemptobj->get_submitted_date());
$this->assertEquals($user->id, $attemptobj->get_userid());
$this->assertTrue($attemptobj->has_response_to_at_least_one_graded_question());
}

/**
* Create a quiz with a random as well as other questions and walk through quiz attempts.
*/
Expand Down

0 comments on commit a0297df

Please sign in to comment.