Skip to content

Commit aaf8d41

Browse files
committed
Add plugintype and additional docs SMS subsystem
1 parent 91c724d commit aaf8d41

File tree

2 files changed

+171
-0
lines changed

2 files changed

+171
-0
lines changed

docs/apis/plugintypes/sms/index.md

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

docs/apis/subsystems/sms/index.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ $message = \core\di::get(\core_sms\manager::class)
2020
recipientuserid: $user->id,
2121
issensitive: false,
2222
async: false,
23+
gatewayid: 22,
2324
);
2425
```
2526

@@ -122,3 +123,47 @@ graph TD
122123
GQ --> |Gateway failed to send the message| GF
123124
end
124125
```
126+
127+
## Getting the list of SMS gateways
128+
129+
Once the gateway is configured from UI, any component implementing the core_sms API can get the list of gateways. The list can also be filtered.
130+
131+
```php title="Getting the list of enabled gateways"
132+
$manager = \core\di::get(\core_sms\manager::class);
133+
$gatewayrecords = $manager->get_gateway_records();
134+
135+
// It is also possible to filter the requst.
136+
$gatewayrecords = $manager->get_gateway_records(['id' => $id]);
137+
138+
// To get all the enabled gateway instances.
139+
$gatewayrecords = $manager->get_enabled_gateway_instances();
140+
```
141+
142+
## Some important hooks to be aware of
143+
144+
SMS API dispatches some hooks which should be assessed and used when this API is implemented in a plugin/component. These hooks helps with
145+
managing the data, like save them from deletion or accidental deactivation from the SMS Gateway management UI while a specific gateway is
146+
being used by a component.
147+
148+
### before_gateway_deleted & before_gateway_disabled
149+
150+
Before deleting or disabling an SMS gateway, these two hooks are dispatched from the core_sms API to allow the components using that specific
151+
gateway to stop that action or do necessary cleanup. It is important to listed to these hooks to prevent data loss or potential issues with a
152+
gateway being used which is deleted or disabled by accident.
153+
154+
```php title="Implement the hooks to check for usage before deletion or deactivation"
155+
156+
public static function check_gateway_usage_in_example_plugin(
157+
before_gateway_deleted|before_gateway_disabled $hook,
158+
): void {
159+
try {
160+
$smsgatewayid = (int)get_config('example_plugin', 'smsgateway');
161+
if ($smsgatewayid && $smsgatewayid === (int)$hook->gateway->id) {
162+
$hook->stop_propagation();
163+
}
164+
} catch (\dml_exception $exception) {
165+
$hook->stop_propagation();
166+
}
167+
}
168+
169+
```

0 commit comments

Comments
 (0)