diff --git a/sms/classes/manager.php b/sms/classes/manager.php index 708b16bfd76..a19445be205 100644 --- a/sms/classes/manager.php +++ b/sms/classes/manager.php @@ -78,12 +78,34 @@ class manager { throw new \coding_exception('Sensitive messages cannot be sent asynchronously'); } + return $this->send_message( + message: $message, + async: $async, + gatewayid: $gatewayid, + ); + } + + /** + * Send a message using the message object. + * + * @param message $message The message object + * @param bool $async Whether this SMS should be sent asynchronously. Note: sensitive messages cannot be sent async + * @param ?int $gatewayid the gateway instance id to send the sms in a specific gateway config + * @return message the message object after trying to send the message + */ + public function send_message( + message $message, + bool $async = true, + ?int $gatewayid = null, + ): message { if ($async) { - // TODO See MDL-81015 for further information. - throw new \coding_exception('Asynchronous sending is not yet implemented'); + $message = $message->with(status: message_status::GATEWAY_QUEUED); + $message = $this->save_message($message); + \core_sms\task\send_sms_task::queue($message); + return $message; } - if (\core_text::strlen($content) > self::MESSAGE_LENGTH_LIMIT) { + 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); diff --git a/sms/classes/task/send_sms_task.php b/sms/classes/task/send_sms_task.php new file mode 100644 index 00000000000..952eaf9ce2f --- /dev/null +++ b/sms/classes/task/send_sms_task.php @@ -0,0 +1,65 @@ +. + +namespace core_sms\task; + +use core\task\adhoc_task; +use core_sms\message; + +/** + * Ad-hoc task to send an SMS. + * + * Please note: sensitive SMS should not be sent from this task, it's already handled via the SMS api to exclude them. + * + * @package core_sms + * @copyright 2025 Safat Shahin + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class send_sms_task extends adhoc_task { + + #[\Override] + public function execute(): void { + + $smsdata = $this->get_custom_data(); + + $manager = \core\di::get(\core_sms\manager::class); + $message = $manager->get_message( + filter: ['id' => $smsdata->messageid], + ); + $manager->send_message( + message: $message, + async: false, + ); + + } + + /** + * Queue the SMS. + * + * @param message $message The message object. + */ + public static function queue( + message $message, + ): void { + $task = new self(); + $task->set_custom_data( + [ + 'messageid' => $message->id, + ] + ); + \core\task\manager::queue_adhoc_task($task); + } +} diff --git a/sms/tests/manager_test.php b/sms/tests/manager_test.php index 6a2379554e4..da4508e9d65 100644 --- a/sms/tests/manager_test.php +++ b/sms/tests/manager_test.php @@ -16,6 +16,8 @@ namespace core_sms; +use core_sms\task\send_sms_task; + /** * Tests for sms manager * @@ -421,21 +423,52 @@ final class manager_test extends \advanced_testcase { ); } - public function test_async_not_supported_yet(): void { + /** + * Test sending SMS asynchronously. + */ + public function test_send_async(): void { $this->resetAfterTest(); - $manager = \core\di::get(\core_sms\manager::class); + $config = new \stdClass(); + $config->priority = 50; - $this->expectException(\coding_exception::class); - $this->expectExceptionMessage('Asynchronous sending is not yet implemented'); - $manager->send( + $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: 'Hello, world!', component: 'core', messagetype: 'test', recipientuserid: null, - async: true, ); + + $this->assertInstanceOf(message::class, $message); + $this->assertIsInt($message->id); + $this->assertEquals(message_status::GATEWAY_QUEUED, $message->status); + $this->assertEquals('Hello, world!', $message->content); + + $messagedbrecords = $manager->get_messages(); + $this->assertInstanceOf(\Generator::class, $messagedbrecords); + $messages = iterator_to_array($messagedbrecords); + $this->assertCount(1, $messages); + + $storedmessage = $manager->get_message(['id' => $message->id]); + $this->assertEquals($message, $storedmessage); + + $adhoctask = \core\task\manager::get_adhoc_tasks(send_sms_task::class); + $this->assertCount(1, $adhoctask); + + // Now lets run the task and check if SMS is sent. + $this->run_all_adhoc_tasks(); + + $message = $manager->get_message(['id' => $message->id]); + $this->assertEquals(message_status::GATEWAY_SENT, $message->status); } public function test_send_no_gateway(): void {