From 4ab988703f84feb1eb045fabf17cde4a4e6857e5 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Wed, 15 Nov 2023 13:51:28 +0000 Subject: [PATCH] MDL-80127 question engine: don't convert null to '' before storing --- question/engine/datalib.php | 3 ++- question/engine/tests/datalib_test.php | 29 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/question/engine/datalib.php b/question/engine/datalib.php index c671c4fa1e8..2c66c9a98b1 100644 --- a/question/engine/datalib.php +++ b/question/engine/datalib.php @@ -149,6 +149,7 @@ class question_engine_data_mapper { /** * Helper method used by insert_question_attempt_step and update_question_attempt_step + * * @param question_attempt_step $step the step to store. * @param int $questionattemptid the question attept id this step belongs to. * @param int $seq the sequence number of this stop. @@ -158,7 +159,7 @@ class question_engine_data_mapper { $record = new stdClass(); $record->questionattemptid = $questionattemptid; $record->sequencenumber = $seq; - $record->state = (string) $step->get_state(); + $record->state = $step->get_state()?->__toString(); $record->fraction = $step->get_fraction(); $record->timecreated = $step->get_timecreated(); $record->userid = $step->get_user_id(); diff --git a/question/engine/tests/datalib_test.php b/question/engine/tests/datalib_test.php index fdb7a702a4f..373f5cbbaf0 100644 --- a/question/engine/tests/datalib_test.php +++ b/question/engine/tests/datalib_test.php @@ -40,6 +40,7 @@ require_once(__DIR__ . '/helpers.php'); * @category test * @copyright 2014 The Open University * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @covers \question_engine_data_mapper */ class datalib_test extends \qbehaviour_walkthrough_test_base { @@ -251,6 +252,34 @@ class datalib_test extends \qbehaviour_walkthrough_test_base { question_engine::delete_questions_usage_by_activity($quba->get_id()); } + public function test_cannot_save_a_step_with_a_missing_state(): void { + global $DB; + + $this->resetAfterTest(); + + // Create a question. + $generator = $this->getDataGenerator()->get_plugin_generator('core_question'); + $cat = $generator->create_question_category(); + $questiondata = $generator->create_question('shortanswer', null, ['category' => $cat->id]); + + // Create a usage. + $quba = question_engine::make_questions_usage_by_activity('test', \context_system::instance()); + $quba->set_preferred_behaviour('deferredfeedback'); + $slot = $quba->add_question(question_bank::load_question($questiondata->id)); + $quba->start_all_questions(); + + // Add a step with a bad state. + $newstep = new \question_attempt_step(); + $newstep->set_state(null); + $addstepmethod = new \ReflectionMethod('question_attempt', 'add_step'); + $addstepmethod->setAccessible(true); + $addstepmethod->invoke($quba->get_question_attempt($slot), $newstep); + + // Verify that trying to save this throws an exception. + $this->expectException(\dml_write_exception::class); + question_engine::save_questions_usage_by_activity($quba); + } + /** * Test cases for {@see test_get_file_area_name()}. *