MDL-63456 qtype_multichoice: Return a default options object if missing

This commit is contained in:
Eric Merrill 2018-10-08 15:46:28 -04:00
parent efea324715
commit 1ddf3b6a0f
2 changed files with 115 additions and 2 deletions

View File

@ -39,11 +39,51 @@ require_once($CFG->libdir . '/questionlib.php');
class qtype_multichoice extends question_type {
public function get_question_options($question) {
global $DB, $OUTPUT;
$question->options = $DB->get_record('qtype_multichoice_options',
array('questionid' => $question->id), '*', MUST_EXIST);
$question->options = $DB->get_record('qtype_multichoice_options', ['questionid' => $question->id]);
if ($question->options === false) {
// If this has happened, then we have a problem.
// For the user to be able to edit or delete this question, we need options.
debugging("Question ID {$question->id} was missing an options record. Using default.", DEBUG_DEVELOPER);
$question->options = $this->create_default_options($question);
}
parent::get_question_options($question);
}
/**
* Create a default options object for the provided question.
*
* @param object $question The queston we are working with.
* @return object The options object.
*/
protected function create_default_options($question) {
// Create a default question options record.
$options = new stdClass();
$options->questionid = $question->id;
// Get the default strings and just set the format.
$options->correctfeedback = get_string('correctfeedbackdefault', 'question');
$options->correctfeedbackformat = FORMAT_HTML;
$options->partiallycorrectfeedback = get_string('partiallycorrectfeedbackdefault', 'question');;
$options->partiallycorrectfeedbackformat = FORMAT_HTML;
$options->incorrectfeedback = get_string('incorrectfeedbackdefault', 'question');
$options->incorrectfeedbackformat = FORMAT_HTML;
$config = get_config('qtype_multichoice');
$options->single = $config->answerhowmany;
if (isset($question->layout)) {
$options->layout = $question->layout;
}
$options->answernumbering = $config->answernumbering;
$options->shuffleanswers = $config->shuffleanswers;
$options->shownumcorrect = 1;
return $options;
}
public function save_question_options($question) {
global $DB;
$context = $question->context;

View File

@ -163,4 +163,77 @@ class qtype_multichoice_test extends advanced_testcase {
}
}
}
/**
* Test to make sure that loading of question options works, including in an error case.
*/
public function test_get_question_options() {
global $DB;
$this->resetAfterTest(true);
$this->setAdminUser();
// Create a complete, in DB question to use.
$questiondata = test_question_maker::get_question_data('multichoice', 'two_of_four');
$formdata = test_question_maker::get_question_form_data('multichoice', 'two_of_four');
$generator = $this->getDataGenerator()->get_plugin_generator('core_question');
$cat = $generator->create_question_category(array());
$formdata->category = "{$cat->id},{$cat->contextid}";
qtype_multichoice_edit_form::mock_submit((array)$formdata);
$form = qtype_multichoice_test_helper::get_question_editing_form($cat, $questiondata);
$this->assertTrue($form->is_validated());
$fromform = $form->get_data();
$returnedfromsave = $this->qtype->save_question($questiondata, $fromform);
// Now get just the raw DB record.
$question = $DB->get_record('question', ['id' => $returnedfromsave->id], '*', MUST_EXIST);
// Load it.
$this->qtype->get_question_options($question);
$this->assertDebuggingNotCalled();
$this->assertInstanceOf(stdClass::class, $question->options);
$options = $question->options;
$this->assertEquals($question->id, $options->questionid);
$this->assertEquals(0, $options->single);
$this->assertCount(4, $options->answers);
// Now we are going to delete the options record.
$DB->delete_records('qtype_multichoice_options', ['questionid' => $question->id]);
// Now see what happens.
$question = $DB->get_record('question', ['id' => $returnedfromsave->id], '*', MUST_EXIST);
$this->qtype->get_question_options($question);
$this->assertDebuggingCalled('Question ID '.$question->id.' was missing an options record. Using default.');
$this->assertInstanceOf(stdClass::class, $question->options);
$options = $question->options;
$this->assertEquals($question->id, $options->questionid);
$this->assertCount(4, $options->answers);
$this->assertEquals(get_string('correctfeedbackdefault', 'question'), $options->correctfeedback);
$this->assertEquals(FORMAT_HTML, $options->correctfeedbackformat);
// We no longer know how many answers, so it just has to guess with the default value.
$this->assertEquals(get_config('qtype_multichoice', 'answerhowmany'), $options->single);
// And finally we try again with no answer either.
$DB->delete_records('question_answers', ['question' => $question->id]);
$question = $DB->get_record('question', ['id' => $returnedfromsave->id], '*', MUST_EXIST);
$this->qtype->get_question_options($question);
$this->assertDebuggingCalled('Question ID '.$question->id.' was missing an options record. Using default.');
$this->assertInstanceOf(stdClass::class, $question->options);
$options = $question->options;
$this->assertEquals($question->id, $options->questionid);
$this->assertCount(0, $options->answers);
}
}