Skip to content

Commit d0189ba

Browse files
authored
feat: v3 (#90)
* feat: v3 - throw exceptions (with ability to ignore specific codes) - deferrable provider - dedicated config file - strict types - fix bad tests * feat: bump sdk verson to v6, add github actions CI * feat: publish config + update readme * fix: scrutinizer bugs * feat: add support for debug to * feat: docs + rethrow errors tests * fix: switch to singleton
1 parent ede4b2c commit d0189ba

17 files changed

+452
-217
lines changed

README.md

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,33 @@ composer require laravel-notification-channels/twilio
3333

3434
### Setting up your Twilio account
3535

36-
Add your Twilio Account SID, Auth Token, and From Number (optional) to your `config/services.php`:
36+
Add your Twilio Account SID, Auth Token, and From Number (optional) to your `.env`:
37+
38+
```dotenv
39+
TWILIO_USERNAME=XYZ # optional when using auth token
40+
TWILIO_PASSWORD=ZYX # optional when using auth token
41+
TWILIO_AUTH_TOKEN=ABCD # optional when using username and password
42+
TWILIO_ACCOUNT_SID=1234 # always required
43+
TWILIO_FROM=100000000 # otional default from
44+
TWILIO_ALPHA_SENDER=HELLO # optional
45+
TWILIO_DEBUG_TO=23423423423 # Set a number that call calls/messages should be routed to for debugging
46+
```
3747

38-
```php
39-
// config/services.php
40-
...
41-
'twilio' => [
42-
'username' => env('TWILIO_USERNAME'), // optional when using auth token
43-
'password' => env('TWILIO_PASSWORD'), // optional when using auth token
44-
'auth_token' => env('TWILIO_AUTH_TOKEN'), // optional when using username and password
45-
'account_sid' => env('TWILIO_ACCOUNT_SID'),
46-
'from' => env('TWILIO_FROM'), // optional
47-
],
48-
...
48+
### Advanced configuration
49+
50+
Run `php artisan vendor:publish --provider="NotificationChannels\Twilio\TwilioProvider"`
51+
```
52+
/config/twilio-notification-channel.php
4953
```
5054

55+
#### Suppressing specific errors or all errors
56+
57+
Publish the config using the above command, and edit the `ignored_error_codes` array. You can get the list of
58+
exception codes from [the documentation](https://www.twilio.com/docs/api/errors).
59+
60+
If you want to suppress all errors, you can set the option to `['*']`. The errors will not be logged but notification
61+
failed events will still be emitted.
62+
5163
## Usage
5264

5365
Now you can use the channel in your `via()` method inside the notification:

composer.json

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "laravel-notification-channels/twilio",
3-
"description": "Provides Twilio notification channel for Laravel.",
3+
"description": "Provides Twilio notification channel for Laravel",
44
"keywords": ["laravel", "twilio", "notification", "sms", "call", "mms"],
55
"license": "MIT",
66
"support": {
@@ -13,15 +13,21 @@
1313
"email": "[email protected]",
1414
"homepage": "https://github.com/gregoriohc",
1515
"role": "Developer"
16+
},
17+
{
18+
"name": "atymic",
19+
"email": "[email protected]",
20+
"homepage": "https://atymic.dev",
21+
"role": "Developer"
1622
}
1723
],
1824
"require": {
1925
"php": ">=7.2",
20-
"twilio/sdk": "~5.16",
21-
"illuminate/notifications": "^5.5 || ^6.0 || ^7.0",
22-
"illuminate/support": "^5.5 || ^6.0 || ^7.0",
23-
"illuminate/events": "^5.5 || ^6.0 || ^7.0",
24-
"illuminate/queue": "^5.5 || ^6.0 || ^7.0"
26+
"twilio/sdk": "~6.0",
27+
"illuminate/notifications": "^5.8 || ^6.0 || ^7.0",
28+
"illuminate/support": "^5.8 || ^6.0 || ^7.0",
29+
"illuminate/events": "^5.8 || ^6.0 || ^7.0",
30+
"illuminate/queue": "^5.8 || ^6.0 || ^7.0"
2531
},
2632
"require-dev": {
2733
"mockery/mockery": "^1.3",
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
3+
return [
4+
'username' => env('TWILIO_USERNAME'), // optional when using auth token
5+
'password' => env('TWILIO_PASSWORD'), // optional when using auth token
6+
'auth_token' => env('TWILIO_AUTH_TOKEN'), // optional when using username and password
7+
'account_sid' => env('TWILIO_ACCOUNT_SID'),
8+
9+
'from' => env('TWILIO_FROM'), // optional
10+
'alphanumeric_sender' => env('TWILIO_ALPHA_SENDER'),
11+
12+
/**
13+
* Specify a number where all calls/messages should be routed. This can be used in development/staging environments
14+
* for testing.
15+
*/
16+
'debug_to' => env('TWILIO_DEBUG_TO'),
17+
18+
/**
19+
* If an exception is thrown with one of these error codes, it will be caught & suppressed.
20+
* To replicate the 2.x behaviour, specify '*' in the array, which will cause all exceptions to be suppressed.
21+
* Suppressed errors will not be logged or reported, but the `NotificationFailed` event will be emitted.
22+
*
23+
* @see https://www.twilio.com/docs/api/errors
24+
*/
25+
'ignored_error_codes' => [
26+
21608, // The 'to' phone number provided is not yet verified for this account.
27+
21211, // Invalid 'To' Phone Number
28+
21614, // 'To' number is not a valid mobile number
29+
21408, // Permission to send an SMS has not been enabled for the region indicated by the 'To' number
30+
],
31+
];

src/Exceptions/CouldNotSendNotification.php

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,37 @@
11
<?php
22

3+
declare(strict_types=1);
4+
35
namespace NotificationChannels\Twilio\Exceptions;
46

5-
use NotificationChannels\Twilio\CallMessage;
6-
use NotificationChannels\Twilio\SmsMessage;
7+
use NotificationChannels\Twilio\TwilioCallMessage;
8+
use NotificationChannels\Twilio\TwilioSmsMessage;
79

810
class CouldNotSendNotification extends \Exception
911
{
10-
/**
11-
* @param mixed $message
12-
*
13-
* @return static
14-
*/
15-
public static function invalidMessageObject($message)
12+
public static function invalidMessageObject($message): self
1613
{
17-
$className = get_class($message) ?: 'Unknown';
14+
$className = is_object($message) ? get_class($message) : 'Unknown';
1815

1916
return new static(
2017
"Notification was not sent. Message object class `{$className}` is invalid. It should
21-
be either `".SmsMessage::class.'` or `'.CallMessage::class.'`');
18+
be either `".TwilioSmsMessage::class.'` or `'.TwilioCallMessage::class.'`');
2219
}
2320

24-
/**
25-
* @return static
26-
*/
27-
public static function missingFrom()
21+
public static function missingFrom(): self
2822
{
2923
return new static('Notification was not sent. Missing `from` number.');
3024
}
3125

32-
/**
33-
* @return static
34-
*/
35-
public static function invalidReceiver()
26+
public static function invalidReceiver(): self
3627
{
3728
return new static(
3829
'The notifiable did not have a receiving phone number. Add a routeNotificationForTwilio
3930
method or a phone_number attribute to your notifiable.'
4031
);
4132
}
4233

43-
public static function missingAlphaNumericSender()
34+
public static function missingAlphaNumericSender(): self
4435
{
4536
return new static(
4637
'Notification was not sent. Missing `alphanumeric_sender` in config'
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace NotificationChannels\Twilio\Exceptions;
6+
7+
class InvalidConfigException extends \Exception
8+
{
9+
public static function missingConfig(): self
10+
{
11+
return new self('Missing config. You must set either the username & password or SID and auth token');
12+
}
13+
}

src/Twilio.php

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,26 +3,19 @@
33
namespace NotificationChannels\Twilio;
44

55
use NotificationChannels\Twilio\Exceptions\CouldNotSendNotification;
6+
use Twilio\Exceptions\TwilioException;
7+
use Twilio\Rest\Api\V2010\Account\CallInstance;
8+
use Twilio\Rest\Api\V2010\Account\MessageInstance;
69
use Twilio\Rest\Client as TwilioService;
710

811
class Twilio
912
{
10-
/**
11-
* @var TwilioService
12-
*/
13+
/** @var TwilioService */
1314
protected $twilioService;
1415

15-
/**
16-
* @var TwilioConfig
17-
*/
18-
private $config;
16+
/** @var TwilioConfig */
17+
public $config;
1918

20-
/**
21-
* Twilio constructor.
22-
*
23-
* @param TwilioService $twilioService
24-
* @param TwilioConfig $config
25-
*/
2619
public function __construct(TwilioService $twilioService, TwilioConfig $config)
2720
{
2821
$this->twilioService = $twilioService;
@@ -32,13 +25,15 @@ public function __construct(TwilioService $twilioService, TwilioConfig $config)
3225
/**
3326
* Send a TwilioMessage to the a phone number.
3427
*
35-
* @param TwilioMessage $message
36-
* @param string $to
28+
* @param TwilioMessage $message
29+
* @param string|null $to
3730
* @param bool $useAlphanumericSender
31+
*
3832
* @return mixed
39-
* @throws \Twilio\Exceptions\TwilioException
33+
* @throws TwilioException
34+
* @throws CouldNotSendNotification
4035
*/
41-
public function sendMessage(TwilioMessage $message, $to, $useAlphanumericSender = false)
36+
public function sendMessage(TwilioMessage $message, ?string $to, bool $useAlphanumericSender = false)
4237
{
4338
if ($message instanceof TwilioSmsMessage) {
4439
if ($useAlphanumericSender && $sender = $this->getAlphanumericSender()) {
@@ -59,11 +54,20 @@ public function sendMessage(TwilioMessage $message, $to, $useAlphanumericSender
5954
* Send an sms message using the Twilio Service.
6055
*
6156
* @param TwilioSmsMessage $message
62-
* @param string $to
63-
* @return \Twilio\Rest\Api\V2010\Account\MessageInstance
57+
* @param string|null $to
58+
*
59+
* @return MessageInstance
60+
* @throws CouldNotSendNotification
61+
* @throws TwilioException
6462
*/
65-
protected function sendSmsMessage(TwilioSmsMessage $message, $to)
63+
protected function sendSmsMessage(TwilioSmsMessage $message, ?string $to): MessageInstance
6664
{
65+
$debugTo = $this->config->getDebugTo();
66+
67+
if ($debugTo !== null) {
68+
$to = $debugTo;
69+
}
70+
6771
$params = [
6872
'body' => trim($message->content),
6973
];
@@ -76,7 +80,7 @@ protected function sendSmsMessage(TwilioSmsMessage $message, $to)
7680
$params['from'] = $from;
7781
}
7882

79-
if (! $from && ! $messagingServiceSid) {
83+
if (empty($from) && empty($messagingServiceSid)) {
8084
throw CouldNotSendNotification::missingFrom();
8185
}
8286

@@ -103,11 +107,13 @@ protected function sendSmsMessage(TwilioSmsMessage $message, $to)
103107
* Make a call using the Twilio Service.
104108
*
105109
* @param TwilioCallMessage $message
106-
* @param string $to
107-
* @return \Twilio\Rest\Api\V2010\Account\CallInstance
108-
* @throws \Twilio\Exceptions\TwilioException
110+
* @param string|null $to
111+
*
112+
* @return CallInstance
113+
* @throws TwilioException
114+
* @throws CouldNotSendNotification
109115
*/
110-
protected function makeCall(TwilioCallMessage $message, $to)
116+
protected function makeCall(TwilioCallMessage $message, ?string $to): CallInstance
111117
{
112118
$params = [
113119
'url' => trim($message->content),
@@ -137,9 +143,9 @@ protected function makeCall(TwilioCallMessage $message, $to)
137143
* Get the from address from message, or config.
138144
*
139145
* @param TwilioMessage $message
140-
* @return string
146+
* @return string|null
141147
*/
142-
protected function getFrom(TwilioMessage $message)
148+
protected function getFrom(TwilioMessage $message): ?string
143149
{
144150
return $message->getFrom() ?: $this->config->getFrom();
145151
}
@@ -148,9 +154,9 @@ protected function getFrom(TwilioMessage $message)
148154
* Get the messaging service SID from message, or config.
149155
*
150156
* @param TwilioSmsMessage $message
151-
* @return string
157+
* @return string|null
152158
*/
153-
protected function getMessagingServiceSid(TwilioSmsMessage $message)
159+
protected function getMessagingServiceSid(TwilioSmsMessage $message): ?string
154160
{
155161
return $message->getMessagingServiceSid() ?: $this->config->getServiceSid();
156162
}
@@ -160,11 +166,9 @@ protected function getMessagingServiceSid(TwilioSmsMessage $message)
160166
*
161167
* @return string|null
162168
*/
163-
protected function getAlphanumericSender()
169+
protected function getAlphanumericSender(): ?string
164170
{
165-
if ($sender = $this->config->getAlphanumericSender()) {
166-
return $sender;
167-
}
171+
return $this->config->getAlphanumericSender();
168172
}
169173

170174
/**
@@ -173,7 +177,7 @@ protected function getAlphanumericSender()
173177
* @param array $optionalParams
174178
* @return Twilio
175179
*/
176-
protected function fillOptionalParams(&$params, $message, $optionalParams)
180+
protected function fillOptionalParams(&$params, $message, $optionalParams): self
177181
{
178182
foreach ($optionalParams as $optionalParam) {
179183
if ($message->$optionalParam) {

0 commit comments

Comments
 (0)