diff --git a/.upgradenotes/MDL-84342-2025020311153786.yml b/.upgradenotes/MDL-84342-2025020311153786.yml new file mode 100644 index 00000000000..8bf1a07c936 --- /dev/null +++ b/.upgradenotes/MDL-84342-2025020311153786.yml @@ -0,0 +1,7 @@ +issueNumber: MDL-84342 +notes: + core_sms: + - message: >- + Introducing a new function \core_sms\gateway::truncate_message() to truncate SMS message content + according to the length limit of the gateway. + type: improved diff --git a/sms/classes/gateway.php b/sms/classes/gateway.php index 22067dad9d9..1dba5c58802 100644 --- a/sms/classes/gateway.php +++ b/sms/classes/gateway.php @@ -34,6 +34,9 @@ use stdClass; abstract class gateway { use Cloneable; + /** @var int The maximum length of a message. */ + protected const MESSAGE_LENGTH_LIMIT = 160 * 3; + /** @var stdClass The configuration for this instance */ public readonly stdClass $config; @@ -128,4 +131,14 @@ abstract class gateway { public function update_message_statuses(array $messages): array { return array_map([$this, 'update_message_status'], $messages); } + + /** + * Truncates the given message to fit the constraints. + * + * @param string $message The message to be truncated. + * @return string The truncated message. + */ + public function truncate_message(string $message): string { + return \core_text::substr($message, 0, static::MESSAGE_LENGTH_LIMIT); + } } diff --git a/sms/classes/manager.php b/sms/classes/manager.php index a19445be205..ad2ef73f92d 100644 --- a/sms/classes/manager.php +++ b/sms/classes/manager.php @@ -27,9 +27,6 @@ use stdClass; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class manager { - /** @var int The maximum length of a message */ - const MESSAGE_LENGTH_LIMIT = 160 * 3; - /** * Create a new SMS manager. * @@ -105,13 +102,12 @@ class manager { return $message; } - if (\core_text::strlen($message->content) > self::MESSAGE_LENGTH_LIMIT) { - $message = $message->with(status: message_status::MESSAGE_OVER_SIZE); - } else if ($gateway = $this->get_gateway_for_message($message, $gatewayid)) { - $message = $message->with(gatewayid: $gateway->id); - $message = $gateway->send( - message: $message, + if ($gateway = $this->get_gateway_for_message($message, $gatewayid)) { + $modifiedmessage = $message->with( + gatewayid: $gateway->id, + content: $gateway->truncate_message($message->content), ); + $message = $gateway->send($modifiedmessage); } else { $message = $message->with(status: message_status::GATEWAY_NOT_AVAILABLE); } diff --git a/sms/tests/fixtures/dummy_gateway.php b/sms/tests/fixtures/dummy_gateway.php index 8cd43971595..f8c82bf75c6 100644 --- a/sms/tests/fixtures/dummy_gateway.php +++ b/sms/tests/fixtures/dummy_gateway.php @@ -26,6 +26,9 @@ use core_sms\message; * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class gateway extends \core_sms\gateway { + /** @var int The maximum length of a message */ + protected const MESSAGE_LENGTH_LIMIT = 160 * 1; + #[\Override] public function send(message $message): message { return $message->with( diff --git a/sms/tests/manager_test.php b/sms/tests/manager_test.php index da4508e9d65..320dc9553c5 100644 --- a/sms/tests/manager_test.php +++ b/sms/tests/manager_test.php @@ -492,6 +492,39 @@ final class manager_test extends \advanced_testcase { $this->assertEmpty($message->gatewayid); } + /** + * Test the truncate content process while sending the SMS. + */ + public function test_send_truncate_content(): void { + $this->resetAfterTest(); + + $config = new \stdClass(); + $config->priority = 50; + + $manager = \core\di::get(\core_sms\manager::class); + $manager->create_gateway_instance( + classname: \smsgateway_dummy\gateway::class, + name: 'dummy', + enabled: true, + config: $config, + ); + + $message = $manager->send( + recipientnumber: '+447123456789', + content: str_repeat('a', 161), + component: 'core', + messagetype: 'test', + recipientuserid: null, + async: false, + ); + + // Expected the message to be truncated with the length limit. + $this->assertEquals( + expected: str_repeat('a', 160), // 160 is the limit of the dummy gateway. + actual: $message->content, + ); + } + public function test_get_messages(): void { $db = $this->createStub(\moodle_database::class); $db->method('get_records')->willReturn([