Skip to content

Commit

Permalink
feat: group by adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
loks0n committed Nov 9, 2023
1 parent 4ee2814 commit faf88d1
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 39 deletions.
78 changes: 55 additions & 23 deletions src/Utopia/Messaging/Adapters/SMS/GEOSMS.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,45 +34,77 @@ public function setLocal(string $callingCode, SMSAdapter $adapter): self
return $this;
}

protected function filterCallingCodesByAdapter(SMSAdapter $adapter): array
{
$result = [];

foreach ($this->localAdapters as $callingCode => $localAdapter) {
if ($localAdapter === $adapter) {
$result[] = $callingCode;
}
}

return $result;
}

protected function process(SMS $message): string
{
$recipientsByCallingCode = $this->groupRecipientsByCallingCode($message->getTo());
$responses = [];
$errors = [];
$results = [];
$recipients = $message->getTo();

foreach ($recipientsByCallingCode as $callingCode => $recipients) {
$adapter = isset($this->localAdapters[$callingCode])
? $this->localAdapters[$callingCode]
: $this->defaultAdapter;
do {
[$nextRecipients, $nextAdapter] = $this->getNextRecipientsAndAdapter($recipients);

try {
$responses[] = $adapter->send(new SMS(
to: $recipients,
content: $message->getContent(),
from: $message->getFrom(),
attachments: $message->getAttachments()
$results[$nextAdapter->getName()] = json_decode($nextAdapter->send(
new SMS(
to: $nextRecipients,
content: $message->getContent(),
from: $message->getFrom(),
attachments: $message->getAttachments()
)
));
} catch (\Exception $e) {
$errors[] = $e;
$results[$nextAdapter->getName()] = [
'type' => 'error',
'message' => $e->getMessage(),
];
}
}

if (count($errors) > 0) {
throw new \Exception('Failed to send SMS to some recipients', 0, $errors[0]);
}
$recipients = \array_diff($recipients, $nextRecipients);
} while (count($recipients) > 0);

return $responses[0];
return \json_encode($results);
}

protected function groupRecipientsByCallingCode(array $recipients): array
protected function getNextRecipientsAndAdapter(array $recipients): array
{
$result = [];
$nextRecipients = [];
$nextAdapter = null;

foreach ($recipients as $recipient) {
$callingCode = CallingCode::fromPhoneNumber($recipient);
$result[$callingCode][] = $recipient;
$adapter = $this->getAdapterByPhoneNumber($recipient);

if ($nextAdapter === null || $adapter === $nextAdapter) {
$nextAdapter = $adapter;
$nextRecipients[] = $recipient;
}
}

return $result;
return [$nextRecipients, $nextAdapter];
}

protected function getAdapterByPhoneNumber(?string $phoneNumber): SMSAdapter
{
$callingCode = CallingCode::fromPhoneNumber($phoneNumber);
if ($callingCode === null || empty($callingCode)) {
return $this->defaultAdapter;
}

if (isset($this->localAdapters[$callingCode])) {
return $this->localAdapters[$callingCode];
}

return $this->defaultAdapter;
}
}
4 changes: 2 additions & 2 deletions src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ class CallingCode

public const NORFOLK_ISLANDS = '672';

public const NORTH_AMERICA = '1';

public const NORTHERN_MARIANA_ISLANDS = '670';

public const NORWAY = '47';
Expand Down Expand Up @@ -365,8 +367,6 @@ class CallingCode

public const URUGUAY = '598';

public const NORTH_AMERICA = '1';

public const VANUATU = '678';

public const VENEZUELA = '58';
Expand Down
2 changes: 2 additions & 0 deletions tests/e2e/SMS/GEOSMS/CallingCodeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ public function testFromPhoneNumber()
{
$this->assertEquals(CallingCode::NORTH_AMERICA, CallingCode::fromPhoneNumber('+11234567890'));
$this->assertEquals(CallingCode::INDIA, CallingCode::fromPhoneNumber('+911234567890'));
$this->assertEquals(CallingCode::ISRAEL, CallingCode::fromPhoneNumber('9721234567890'));
$this->assertEquals(CallingCode::UNITED_ARAB_EMIRATES, CallingCode::fromPhoneNumber('009711234567890'));
$this->assertEquals(CallingCode::UNITED_KINGDOM, CallingCode::fromPhoneNumber('011441234567890'));
$this->assertEquals(null, CallingCode::fromPhoneNumber('2'));
}
}
87 changes: 73 additions & 14 deletions tests/e2e/SMS/GEOSMSTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ class GEOSMSTest extends Base
public function testSendSMSUsingDefaultAdapter()
{
$defaultAdapterMock = $this->createMock(SMSAdapter::class);
$defaultAdapterMock->method('getMaxMessagesPerRequest')
->willReturn(1);
$defaultAdapterMock->method('getName')
->willReturn('default');
$defaultAdapterMock->method('send')
->willReturn(json_encode(['status' => 'success']));

Expand All @@ -28,26 +28,85 @@ public function testSendSMSUsingDefaultAdapter()
from: $from
);

$result = json_decode($adapter->send($message));
$result = json_decode($adapter->send($message), true);

$this->assertEquals('success', $result->status);
$this->assertEquals(1, count($result));
$this->assertEquals('success', $result['default']['status']);
}

public function testSendSMSUsingLocalAdapter()
{
$defaultAdapterMock = $this->createMock(SMSAdapter::class);
$defaultAdapterMock->method('getMaxMessagesPerRequest')
->willReturn(1);
$localAdapterMock = $this->createMock(SMSAdapter::class);
$localAdapterMock->method('getMaxMessagesPerRequest')
->willReturn(1);
$localAdapterMock->method('getName')
->willReturn('local');
$localAdapterMock->method('send')
->willReturn(json_encode(['status' => 'success', 'adapter' => 'local']));
->willReturn(json_encode(['status' => 'success']));

$adapter = new GEOSMS($defaultAdapterMock);
$adapter->setLocal(CallingCode::INDIA, $localAdapterMock);

$to = ['+911234567890'];
$from = 'Sender';

$message = new SMS(
to: $to,
content: 'Test Content',
from: $from
);

$result = json_decode($adapter->send($message), true);

$this->assertEquals(1, count($result));
$this->assertEquals('success', $result['local']['status']);
}

public function testSendSMSUsingLocalAdapterAndDefault()
{
$defaultAdapterMock = $this->createMock(SMSAdapter::class);
$defaultAdapterMock->method('getName')
->willReturn('default');
$defaultAdapterMock->method('send')
->willReturn(json_encode(['status' => 'success']));
$localAdapterMock = $this->createMock(SMSAdapter::class);
$localAdapterMock->method('getName')
->willReturn('local');
$localAdapterMock->method('send')
->willReturn(json_encode(['status' => 'success']));

$adapter = new GEOSMS($defaultAdapterMock);
$adapter->setLocal(CallingCode::INDIA, $localAdapterMock);

$to = ['+911234567890', '+11234567890'];
$from = 'Sender';

$message = new SMS(
to: $to,
content: 'Test Content',
from: $from
);

$result = json_decode($adapter->send($message), true);

$this->assertEquals(2, count($result));
$this->assertEquals('success', $result['local']['status']);
$this->assertEquals('success', $result['default']['status']);
}

public function testSendSMSUsingGroupedLocalAdapter()
{
$defaultAdapterMock = $this->createMock(SMSAdapter::class);
$localAdapterMock = $this->createMock(SMSAdapter::class);
$localAdapterMock->method('getName')
->willReturn('local');
$localAdapterMock->method('send')
->willReturn(json_encode(['status' => 'success']));

$adapter = new GEOSMS($defaultAdapterMock);
$adapter->setLocal(CallingCode::UNITED_KINGDOM, $localAdapterMock);
$adapter->setLocal(CallingCode::INDIA, $localAdapterMock);
$adapter->setLocal(CallingCode::NORTH_AMERICA, $localAdapterMock);

$to = ['+441234567890'];
$to = ['+911234567890', '+11234567890'];
$from = 'Sender';

$message = new SMS(
Expand All @@ -56,9 +115,9 @@ public function testSendSMSUsingLocalAdapter()
from: $from
);

$result = json_decode($adapter->send($message));
$result = json_decode($adapter->send($message), true);

$this->assertEquals('success', $result->status);
$this->assertEquals('local', $result->adapter);
$this->assertEquals(1, count($result));
$this->assertEquals('success', $result['local']['status']);
}
}

0 comments on commit faf88d1

Please sign in to comment.