From 585c8d6b487186b59e71f7fa01bab104bd9ca48f Mon Sep 17 00:00:00 2001 From: Mark Johnson Date: Mon, 30 Jun 2025 11:07:14 +0100 Subject: [PATCH] MDL-85881 questions: Handle multi-byte names during migration We were using strlen() instead of core_text::strlen() when checking the length of a question bank name created during the migration. This meant that multibyte strings were counted as being too long, even though they were within the character limit. --- .../local/bank/question_bank_helper.php | 2 +- .../local/bank/question_bank_helper_test.php | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/question/classes/local/bank/question_bank_helper.php b/question/classes/local/bank/question_bank_helper.php index 378b84ec0eb..90e4f39e607 100644 --- a/question/classes/local/bank/question_bank_helper.php +++ b/question/classes/local/bank/question_bank_helper.php @@ -582,7 +582,7 @@ class question_bank_helper { } } - if (strlen($bankname) > self::BANK_NAME_MAX_LENGTH) { + if (\core_text::strlen($bankname) > self::BANK_NAME_MAX_LENGTH) { throw new \coding_exception( 'The provided bankname is too long for the database field.', 'Use question_bank_helper::get_bank_name_string to get a suitably truncated name.', diff --git a/question/tests/local/bank/question_bank_helper_test.php b/question/tests/local/bank/question_bank_helper_test.php index b58084f610a..c10496a2cdb 100644 --- a/question/tests/local/bank/question_bank_helper_test.php +++ b/question/tests/local/bank/question_bank_helper_test.php @@ -280,6 +280,33 @@ final class question_bank_helper_test extends \advanced_testcase { ); } + /** + * Create a default instance, passing a multibyte-character name. + * + * The name has more bytes than the max length, but is within the character limit as they are multibyte characters. + */ + public function test_create_default_open_instance_with_multibyte_name(): void { + $this->resetAfterTest(); + self::setAdminUser(); + + $coursename = ''; + while (strlen($coursename) < question_bank_helper::BANK_NAME_MAX_LENGTH) { + $coursename .= '🙂'; + } + $course = self::getDataGenerator()->create_course(['shortname' => '🙂']); + $bankname = get_string('defaultbank', 'core_question', ['coursename' => $coursename]); + $this->assertTrue(strlen($bankname) > question_bank_helper::BANK_NAME_MAX_LENGTH); + $this->assertTrue(\core_text::strlen($bankname) < question_bank_helper::BANK_NAME_MAX_LENGTH); + + question_bank_helper::create_default_open_instance($course, $bankname); + + $modinfo = get_fast_modinfo($course); + $cminfos = $modinfo->get_instances_of('qbank'); + $this->assertCount(1, $cminfos); + $cminfo = reset($cminfos); + $this->assertEquals($bankname, $cminfo->get_name()); + } + /** * Assert that viewing a question bank logs the view for that user up to a maximum of 5 unique bank views. *