Skip to content

Commit

Permalink
MDL-43733 use any auto-saved responses when questions are finished.
Browse files Browse the repository at this point in the history
Before this, autosave was only working to save data when a student went
back in to continue an attempt. If the student, having crashed out,
never went back in and continued the attempt, their auto-saved responses
were not used when the attempt was automatically finished. That was a
rather bad oversight, which should now be fixed.
  • Loading branch information
timhunt committed Jan 17, 2014
1 parent f05e25d commit 3d96b49
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 0 deletions.
19 changes: 19 additions & 0 deletions question/engine/questionattempt.php
Expand Up @@ -869,6 +869,24 @@ public function discard_autosaved_step() {
$this->observer->notify_step_deleted($autosaved, $this);
}

/**
* If there is an autosaved step, convert it into a real save, so that it
* is preserved.
*/
protected function convert_autosaved_step_to_real_step() {
if ($this->autosavedstep === null) {
return;
}

$laststep = end($this->steps);
if ($laststep !== $this->autosavedstep) {
throw new coding_exception('Cannot convert autosaved step to real step, since other steps have been added.');
}

$this->observer->notify_step_modified($this->autosavedstep, $this, key($this->steps));
$this->autosavedstep = null;
}

/**
* Use a strategy to pick a variant.
* @param question_variant_selection_strategy $variantstrategy a strategy.
Expand Down Expand Up @@ -1174,6 +1192,7 @@ public function process_autosave($submitteddata, $timestamp = null, $userid = nu
* @param int $userid the user to attribute the aciton to. (If not given, use the current user.)
*/
public function finish($timestamp = null, $userid = null) {
$this->convert_autosaved_step_to_real_step();
$this->process_action(array('-finish' => 1), $timestamp, $userid);
}

Expand Down
57 changes: 57 additions & 0 deletions question/engine/tests/questionusage_autosave_test.php
Expand Up @@ -628,4 +628,61 @@ public function test_autosave_with_wrong_seq_number_ignored() {

$this->delete_quba();
}

public function test_finish_with_unhandled_autosave_data() {
$this->resetAfterTest();
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
$cat = $generator->create_question_category();
$question = $generator->create_question('shortanswer', null,
array('category' => $cat->id));

// Start attempt at a shortanswer question.
$q = question_bank::load_question($question->id);
$this->start_attempt_at_question($q, 'deferredfeedback', 1);

$this->check_current_state(question_state::$todo);
$this->check_current_mark(null);
$this->check_step_count(1);

// Process a response and check the expected result.
$this->process_submission(array('answer' => 'cat'));

$this->check_current_state(question_state::$complete);
$this->check_current_mark(null);
$this->check_step_count(2);
$this->save_quba();

// Now check how that is re-displayed.
$this->render();
$this->check_output_contains_text_input('answer', 'cat');
$this->check_output_contains_hidden_input(':sequencecheck', 2);

// Process an autosave.
$this->load_quba();
$this->process_autosave(array('answer' => 'frog'));
$this->check_current_state(question_state::$complete);
$this->check_current_mark(null);
$this->check_step_count(3);
$this->save_quba();

// Now check how that is re-displayed.
$this->load_quba();
$this->render();
$this->check_output_contains_text_input('answer', 'frog');
$this->check_output_contains_hidden_input(':sequencecheck', 2);

// Now finishe the attempt, without having done anything since the autosave.
$this->finish();
$this->save_quba();

// Now check how that has been graded and is re-displayed.
$this->load_quba();
$this->check_current_state(question_state::$gradedright);
$this->check_current_mark(1);
$this->render();
$this->check_output_contains_text_input('answer', 'frog', false);
$this->check_output_contains_hidden_input(':sequencecheck', 4);

$this->delete_quba();
}
}

0 comments on commit 3d96b49

Please sign in to comment.