MDL-80127 question engine: prevent fatal errors from old bad data

This commit is contained in:
Tim Hunt 2023-11-15 13:58:46 +00:00
parent 8f2f95bd28
commit 7311dff041
3 changed files with 27 additions and 3 deletions

View File

@ -159,7 +159,7 @@ class question_engine_data_mapper {
$record = new stdClass();
$record->questionattemptid = $questionattemptid;
$record->sequencenumber = $seq;
$record->state = $step->get_state() ?? $step->get_state()->__toString() : null;
$record->state = $step->get_state() ? $step->get_state()->__toString() : null;
$record->fraction = $step->get_fraction();
$record->timecreated = $step->get_timecreated();
$record->userid = $step->get_user_id();

View File

@ -111,10 +111,23 @@ abstract class question_state {
}
/**
* Get the instance of this class for a given state name.
*
* @param string $name a state name.
* @return question_state the state with that name.
* @return question_state|null the state with that name. (Null only in an exceptional case.)
*/
public static function get($name) {
public static function get(string $name): ?question_state {
// In the past, there was a bug where null states got stored
// in the database as an empty string, which was wrong because
// the state column should be NOT NULL.
// That is no longer possible, but we need to avoid exceptions
// for people with old bad data in their database.
if ($name === '') {
debugging('Attempt to create a state from an empty string. ' .
'This is probably a sign of bad data in your database. See MDL-80127.');
return null;
}
return self::$$name;
}

View File

@ -31,6 +31,7 @@ require_once($CFG->libdir . '/questionlib.php');
* @category test
* @copyright 2009 The Open University
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @covers \question_state
*/
class questionstate_test extends \advanced_testcase {
public function test_is_active() {
@ -154,4 +155,14 @@ class questionstate_test extends \advanced_testcase {
$this->assertEquals(question_state::$mangrright,
question_state::$gradedpartial->corresponding_commented_state(1));
}
public function test_get(): void {
$this->assertEquals(question_state::$todo, question_state::get('todo'));
}
public function test_get_bad_data(): void {
question_state::get('');
$this->assertDebuggingCalled('Attempt to create a state from an empty string. ' .
'This is probably a sign of bad data in your database. See MDL-80127.');
}
}