8000 [Notifier] Add Bandwidth bridge · symfony/symfony@52807b7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 52807b7

Browse files
committed
[Notifier] Add Bandwidth bridge
1 parent 69f46f2 commit 52807b7

18 files changed

+728
-1
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
use Symfony\Component\Mime\MimeTypes;
128128
use Symfony\Component\Notifier\Bridge\AllMySms\AllMySmsTransportFactory;
129129
use Symfony\Component\Notifier\Bridge\AmazonSns\AmazonSnsTransportFactory;
130+
use Symfony\Component\Notifier\Bridge\Bandwidth\BandwidthTransportFactory;
130131
use Symfony\Component\Notifier\Bridge\Chatwork\ChatworkTransportFactory;
131132
use Symfony\Component\Notifier\Bridge\Clickatell\ClickatellTransportFactory;
132133
use Symfony\Component\Notifier\Bridge\ContactEveryone\ContactEveryoneTransportFactory;
@@ -2548,6 +2549,7 @@ private function registerNotifierConfiguration(array $config, ContainerBuilder $
25482549
$classToServices = [
25492550
AllMySmsTransportFactory::class => 'notifier.transport_factory.all-my-sms',
25502551
AmazonSnsTransportFactory::class => 'notifier.transport_factory.amazon-sns',
2552+
BandwidthTransportFactory::class => 'notifier.transport_factory.bandwidth',
25512553
ChatworkTransportFactory::class => 'notifier.transport_factory.chatwork',
25522554
ClickatellTransportFactory::class => 'notifier.transport_factory.clickatell',
25532555
ContactEveryoneTransportFactory::class => 'notifier.transport_factory.contact-everyone',

src/Symfony/Bundle/FrameworkBundle/Resources/config/notifier_transports.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
use Symfony\Component\Notifier\Bridge\AllMySms\AllMySmsTransportFactory;
1515
use Symfony\Component\Notifier\Bridge\AmazonSns\AmazonSnsTransportFactory;
16+
use Symfony\Component\Notifier\Bridge\Bandwidth\BandwidthTransportFactory;
1617
use Symfony\Component\Notifier\Bridge\Chatwork\ChatworkTransportFactory;
1718
use Symfony\Component\Notifier\Bridge\Clickatell\ClickatellTransportFactory;
1819
use Symfony\Component\Notifier\Bridge\ContactEveryone\ContactEveryoneTransportFactory;
@@ -287,5 +288,9 @@
287288
->parent('notifier.transport_factory.abstract')
288289
->tag('chatter.transport_factory')
289290

291+
->set('notifier.transport_factory.bandwidth', BandwidthTransportFactory::class)
292+
->parent('notifier.transport_factory.abstract')
293+
->tag('texter.transport_factory')
294+
290295
;
291296
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/Tests export-ignore
2+
/phpunit.xml.dist export-ignore
3+
/.gitattributes export-ignore
4+
/.gitignore export-ignore
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
vendor/
2+
composer.lock
3+
phpunit.xml
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<?php
2+
/*
3+
* This file is part of the Symfony package.
4+
*
5+
* (c) Fabien Potencier <fabien@symfony.com>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace Symfony\Component\Notifier\Bridge\Bandwidth;
12+
13+
use Symfony\Component\Notifier\Message\MessageOptionsInterface;
14+
15+
/**
16+
* @author gnito-org <https://github.com/gnito-org>
17+
*/
18+
final class BandwidthOptions implements MessageOptionsInterface
19+
{
20+
private array $options;
21+
22+
public function __construct(array $options = [])
23+
{
24+
$this->options = $options;
25+
}
26+
27+
public function getAccountId(): ?string
28+
{
29+
return $this->options['account_id'] ?? null;
30+
}
31+
32+
public function getApplicationId(): ?string
33+
{
34+
return $this->options['application_id'] ?? null;
35+
}
36+
37+
public function getExpiration(): ?string
38+
{
39+
return $this->options['expiration'] ?? null;
40+
}
41+
42+
public function getFrom(): ?string
43+
{
44+
return $this->options['from'] ?? null;
45+
}
46+
47+
public function getMedia(): ?array
48+
{
49+
return $this->options['media'] ?? null;
50+
}
51+
52+
public function getPriority(): ?string
53+
{
54+
return $this->options['priority'] ?? null;
55+
}
56+
57+
public function getRecipientId(): ?string
58+
{
59+
return $this->options['recipient_id'] ?? null;
60+
}
61+
62+
public function getTag(): ?string
63+
{
64+
return $this->options['tag'] ?? null;
65+
}
66+
67+
public function getTo(): ?array
68+
{
69+
return $this->options['to'] ?? null;
70+
}
71+
72+
public function setAccountId(string $accountId): self
73+
{
74+
$this->options['account_id'] = $accountId;
75+
return $this;
76+
}
77+
78+
public function setApplicationId(string $applicationId): self
79+
{
80+
$this->options['application_id'] = $applicationId;
81+
return $this;
82+
}
83+
84+
public function setExpiration(string $expiration): self
85+
{
86+
$this->options['expiration'] = $expiration;
87+
return $this;
88+
}
89+
90+
public function setFrom(string $from): self
91+
{
92+
$this->options['from'] = $from;
93+
return $this;
94+
}
95+
96+
public function setMedia(array $media): self
97+
{
98+
$this->options['media'] = $media;
99+
return $this;
100+
}
101+
102+
public function setPriority(string $priority): self
103+
{
104+
$this->options['priority'] = $priority;
105+
return $this;
106+
}
107+
108+
public function setRecipientId(string $id): self
109+
{
110+
$this->options['recipient_id'] = $id;
111+
return $this;
112+
}
113+
114+
public function setTag(string $tag): self
115+
{
116+
$this->options['tag'] = $tag;
117+
return $this;
118+
}
119+
120+
public function setTo(array $to): self
121+
{
122+
$this->options['to'] = $to;
123+
return $this;
124+
}
125+
126+
public function toArray(): array
127+
{
128+
return $this->options;
129+
}
130+
}
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
<?php
2+
/*
3+
* This file is part of the Symfony package.
4+
*
5+
* (c) Fabien Potencier <fabien@symfony.com>
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace Symfony\Component\Notifier\Bridge\Bandwidth;
12+
13+
use Symfony\Component\Notifier\Exception\InvalidArgumentException;
14+
use Symfony\Component\Notifier\Exception\TransportException;
15+
use Symfony\Component\Notifier\Exception\UnsupportedMessageTypeException;
16+
use Symfony\Component\Notifier\Message\MessageInterface;
17+
use Symfony\Component\Notifier\Message\SentMessage;
18+
use Symfony\Component\Notifier\Message\SmsMessage;
19+
use Symfony\Component\Notifier\Transport\AbstractTransport;
20+
use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
21+
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
22+
use Symfony\Contracts\HttpClient\HttpClientInterface;
23+
24+
/**
25+
* @author gnito-org <https://github.com/gnito-org>
26+
*/
27+
final class BandwidthTransport extends AbstractTransport
28+
{
29+
protected const HOST = 'messaging.bandwidth.com';
30+
31+
private string $username;
32+
33+
private string $from;
34+
35+
private string $accountId;
36+
37+
private string $applicationId;
38+
39+
private ?string $priority;
40+
41+
private string $password;
42+
43+
public function __construct(
44+
string $username,
45+
#[\SensitiveParameter] string $password,
46+
string $from,
47+
string $accountId,
48+
string $applicationId,
49+
?string $priority,
50+
HttpClientInterface $client = null,
51+
EventDispatcherInterface $dispatcher = null
52+
)
53+
{
54+
$this->username = $username;
55+
$this->password = $password;
56+
$this->from = $from;
57+
$this->accountId = $accountId;
58+
$this->applicationId = $applicationId;
59+
$this->priority = $priority;
60+
parent::__construct(
61+
$client,
62+
$dispatcher
63+
);
64+
}
65+
66+
public function __toString(): string
67+
{
68+
return sprintf(
69+
'bandwidth://%s?from=%s&account_id=%s&application_id=%s&priority=%s',
70+
$this->getEndpoint(),
71+
$this->from,
72+
$this->accountId,
73+
$this->applicationId,
74+
$this->priority
75+
);
76+
}
77+
78+
public function supports(MessageInterface $message): bool
79+
{
80+
return $message instanceof SmsMessage;
81+
}
82+
83+
/**
84+
* https://dev.bandwidth.com/apis/messaging/#tag/Messages/operation/createMessage
85+
*/
86+
protected function doSend(MessageInterface $message): SentMessage
87+
{
88+
if (!$message instanceof SmsMessage) {
89+
throw new UnsupportedMessageTypeException(
90+
__CLASS__,
91+
SmsMessage::class,
92+
$message
93+
);
94+
}
95+
$opts = $message->getOptions();
96+
$options = $opts ? $opts->toArray() : [];
97+
$options['text'] = $message->getSubject();
98+
$options['from'] = $options['from'] ?? $this->from;
99+
$options['to'] = $options['to'] ?? [$message->getPhone()];
100+
$options['account_id'] = $options['account_id'] ?? $this->accountId;
101+
$options['applicationId'] = $options['application_id'] ?? $this->applicationId;
102+
unset($options['application_id']);
103+
if (!isset($options['priority']) && $this->priority) {
104+
$options['priority'] = $this->priority;
105+
}
106+
if (!preg_match(
107+
'/^\+[1-9]\d{1,14}$/',
108+
$this->from
109+
)) {
110+
throw new InvalidArgumentException(
111+
sprintf(
112+
'The "From" number "%s" is not a valid phone number. The number must be in E.164 format.',
113+
$this->from
114+
)
115+
);
116+
}
117+
if (!preg_match(
118+
'/^\+[1-9]\d{1,14}$/',
119+
$message->getPhone()
120+
)) {
121+
throw new InvalidArgumentException(
122+
sprintf(
123+
'The "To" number "%s" is not a valid phone number. The number must be in E.164 format.',
124+
$message->getPhone()
125+
)
126+
);
127+
}
128+
$endpoint = sprintf(
129+
'https://%s/api/v2/users/%s/messages',
130+
$this->getEndpoint(),
131+
$options['account_id']
132+
);
133+
unset($options['accountId']);
134+
$response = $this->client->request(
135+
'POST',
136+
$endpoint,
137+
[
138+
'auth_basic' => $this->username . ':' . $this->password,
139+
'json' => array_filter($options),
140+
]
141+
);
142+
try {
143+
$statusCode = $response->getStatusCode();
144+
} catch (TransportExceptionInterface $e) {
145+
throw new TransportException(
146+
'Could not reach the remote Bandwidth server.',
147+
$response,
148+
0,
149+
$e
150+
);
151+
}
152+
if (202 !== $statusCode) {
153+
$error = $response->toArray(false);
154+
throw new TransportException(
155+
sprintf(
156+
'Unable to send the SMS - %s - %s',
157+
$error['type'],
158+
$error['description']
159+
),
160+
$response
161+
);
162+
}
163+
$success = $response->toArray(false);
164+
$sentMessage = new SentMessage(
165+
$message,
166+
(string) $this
167+
);
168+
$sentMessage->setMessageId($success['id']);
169+
return $sentMessage;
170+
}
171+
}

0 commit comments

Comments
 (0)
0