Skip to content

Commit b945eef

Browse files
Add plugintype and API docs for SMS subsystem
Co-authored-by: David Woloszyn <[email protected]>
1 parent 3af23a6 commit b945eef

File tree

2 files changed

+186
-2
lines changed

2 files changed

+186
-2
lines changed

docs/apis/plugintypes/sms/index.md

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
---
2+
title: SMS gateway
3+
tags:
4+
- SMS
5+
- Gateway
6+
- Notification
7+
---
8+
9+
<Since version="4.5" issueNumber="MDL-83406" />
10+
11+
SMS gateway plugins allow you to create SMS gateway providers.
12+
Providers are an interface between [SMS API](/apis/subsystems/sms/index.md) and the external SMS provider (e.g. Amazon Web Services).
13+
This allows for the sending of SMS notifications to users from your Moodle instance.
14+
15+
For example, you set up MFA (Multi-Factor Authentication) in Moodle and choose 'AWS' as your SMS gateway provider.
16+
This enables users to receive SMS notifications as part of the authentication process.
17+
18+
## File structure
19+
20+
SMS gateway plugins are located in the `/sms/gateway` directory. A plugin should not include any custom files outside its own
21+
plugin folder.
22+
23+
Each plugin is in a separate subdirectory and consists of a number of mandatory files and any other files the developer is going to use. See the [common plugin files](/apis/commonfiles/index.mdx) documentation for other files which may be useful in your plugin.
24+
25+
<details>
26+
<summary>The directory layout for the `smsgateway` plugin.</summary>
27+
28+
```console
29+
sms/gateway/example
30+
├── classes
31+
│   ├── gateway.php
32+
│   ├── hook_listener.php
33+
│   └── privacy
34+
│   └── provider.php
35+
├── lang
36+
│   └── en
37+
│   └── smsgateway_example.php
38+
├── settings.php
39+
└── version.php
40+
```
41+
42+
</details>
43+
44+
## Key files
45+
46+
There are a number of key files within the SMS gateway plugin which will need to be configured for correct functionality.
47+
48+
- gateway.php
49+
- hook_listener.php
50+
51+
### gateway.php
52+
53+
Each plugin must create a class called `gateway` which extends the `\core_sms\gateway` class.
54+
The SMS API will use the extended methods from this class.
55+
56+
```php title="Implementing the base SMS gateway"
57+
58+
class gateway extends \core_sms\gateway {
59+
60+
#[\Override]
61+
public function send(
62+
message $message,
63+
): message {
64+
// Sample code to send an SMS message.
65+
$config = (object)json_decode($awsconfig, true, 512, JSON_THROW_ON_ERROR);
66+
$class = '\smsgateway_aws\local\service\\' . $config->gateway;
67+
$recipientnumber = manager::format_number(
68+
phonenumber: $message->recipientnumber,
69+
countrycode: isset($config->countrycode) ?? null,
70+
);
71+
if (class_exists($class)) {
72+
$status = call_user_func(
73+
$class . '::send_sms_message',
74+
$message->content,
75+
$recipientnumber,
76+
$config,
77+
);
78+
}
79+
return $message->with(
80+
status: $status,
81+
);
82+
}
83+
84+
#[\Override]
85+
public function get_send_priority(message $message): int {
86+
return 50;
87+
}
88+
}
89+
90+
```
91+
92+
### hook_listener.php
93+
94+
[Hooks](/apis/core/hooks/index.md) can be dispatched from the SMS API which the plugin can then listened to.
95+
It is necessary for plugins developers to assess these hooks and implement accordingly.
96+
97+
#### after_sms_gateway_form_hook
98+
99+
This hook will allow plugins to add required form fields to assist users in configuring their SMS gateway.
100+
101+
```php title="Listener method for after_sms_gateway_form_hook"
102+
103+
public static function set_form_definition_for_aws_sms_gateway(after_sms_gateway_form_hook $hook): void {
104+
if ($hook->plugin !== 'smsgateway_example') {
105+
return;
106+
}
107+
108+
$gateways = [
109+
'smsgateway_example' => get_string('list', 'smsgateway_example'),
110+
];
111+
$mform->addElement(
112+
'select',
113+
'gateway',
114+
get_string('gateway', 'smsgateway_example'),
115+
$gateways,
116+
);
117+
}
118+
119+
```
120+
121+
:::info
122+
123+
For a real plugin example, see the [AWS SMS Gateway plugin](https://github.com/moodle/moodle/tree/main/sms/gateway/aws).
124+
125+
:::

docs/apis/subsystems/sms/index.md

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
11
---
22
title: SMS API
3+
tags:
4+
- SMS
35
---
46

57
<Since version="4.5" issueNumber="MDL-79808" />
68

7-
The SMS API lets you send SMS messages using configured gateways, fetch messages that were previously sent, and check on their status.
9+
The SMS API allows developers to implement SMS-related features into their plugins.
10+
The subsystem contains an SMS Manager class `\core_sms\manager` which facilitates the actions performed by the API.
11+
12+
Some of the actions made possible are:
13+
14+
- Sending messages
15+
- Fetching messages
16+
- Checking the status of a message
17+
- Getting SMS gateways.
18+
19+
Currently, the design of the SMS API features the following plugin types:
20+
21+
- [SMS gateway](/apis/plugintypes/sms/index.md)
822

923
## Sending an SMS
1024

@@ -20,12 +34,13 @@ $message = \core\di::get(\core_sms\manager::class)
2034
recipientuserid: $user->id,
2135
issensitive: false,
2236
async: false,
37+
gatewayid: 22,
2338
);
2439
```
2540

2641
:::info Message lengths
2742

28-
A single SMS sent by the API may consist of up to 480 UTF-8 characters. It is up to the message _gateway_ plugin to determine how this message is sent to the recipient.
43+
A single SMS sent by the API may consist of up to 480 UTF-8 characters. It is up to the message _gateway plugin_ to determine how this message is sent to the recipient.
2944

3045
Any message longer than the maximum length will be immediately rejected.
3146

@@ -122,3 +137,47 @@ graph TD
122137
GQ --> |Gateway failed to send the message| GF
123138
end
124139
```
140+
141+
## Getting SMS gateways
142+
143+
[SMS gateways](/apis/plugintypes/sms/index.md) are plugins that provide a way to interface with external SMS providers.
144+
Once a gateway is configured, any component implementing the SMS API can get a list of gateways.
145+
146+
```php title="Getting the list of enabled gateways"
147+
$manager = \core\di::get(\core_sms\manager::class);
148+
$gatewayrecords = $manager->get_gateway_records();
149+
150+
// It is also possible to filter the request.
151+
$gatewayrecords = $manager->get_gateway_records(['id' => $id]);
152+
153+
// To get all the enabled gateway instances.
154+
$gatewayrecords = $manager->get_enabled_gateway_instances();
155+
```
156+
157+
## Important hooks
158+
159+
The SMS API dispatches some [hooks](/apis/core/hooks/index.md) which should be considered when implemented by a plugin/component.
160+
161+
- before_gateway_deleted
162+
- before_gateway_disabled
163+
164+
Before deleting or disabling an [SMS gateways](/apis/plugintypes/sms/index.md), these two hooks are dispatched from the SMS API.
165+
This allows components that are actively using that gateway to stop the action, or do necessary cleanup.
166+
Listening to these hooks is crucial to avoid data loss or accidental deletion when disabling an active gateway.
167+
168+
```php title="Implement the hooks to check for usage before deletion or deactivation"
169+
170+
public static function check_gateway_usage_in_example_plugin(
171+
before_gateway_deleted|before_gateway_disabled $hook,
172+
): void {
173+
try {
174+
$smsgatewayid = (int)get_config('example_plugin', 'smsgateway');
175+
if ($smsgatewayid && $smsgatewayid === (int)$hook->gateway->id) {
176+
$hook->stop_propagation();
177+
}
178+
} catch (\dml_exception $exception) {
179+
$hook->stop_propagation();
180+
}
181+
}
182+
183+
```

0 commit comments

Comments
 (0)