diff --git a/.github/workflows/analyse.yml b/.github/workflows/analyse.yml
new file mode 100644
index 00000000..72ed14c1
--- /dev/null
+++ b/.github/workflows/analyse.yml
@@ -0,0 +1,20 @@
+name: "Static Analysis"
+
+on: [pull_request]
+jobs:
+ analyse:
+ name: Analyse
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 2
+
+ - run: git checkout HEAD^2
+
+ - name: Run Static Analysis
+ run: |
+ docker run --rm -v $PWD:/app composer sh -c \
+ "composer install --profile --ignore-platform-reqs && composer analyse"
diff --git a/.github/workflows/linter.yml b/.github/workflows/lint.yml
similarity index 100%
rename from .github/workflows/linter.yml
rename to .github/workflows/lint.yml
diff --git a/.github/workflows/tests.yml b/.github/workflows/test.yml
similarity index 93%
rename from .github/workflows/tests.yml
rename to .github/workflows/test.yml
index 552b207d..47086952 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/test.yml
@@ -40,6 +40,8 @@ jobs:
VONAGE_API_SECRET: ${{ secrets.VONAGE_API_SECRET }}
VONAGE_TO: ${{ secrets.VONAGE_TO }}
VONAGE_FROM: ${{ secrets.VONAGE_FROM }}
+ DISCORD_WEBHOOK_ID: ${{ secrets.DISCORD_WEBHOOK_ID }}
+ DISCORD_WEBHOOK_TOKEN: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
run: |
docker compose up -d --build
sleep 5
diff --git a/README.md b/README.md
index d745b630..363d928e 100644
--- a/README.md
+++ b/README.md
@@ -21,8 +21,8 @@ composer require utopia-php/messaging
send($message);
send($message);
=8.0.0",
"ext-curl": "*"
},
- "platform-dev": [],
+ "platform-dev": {
+ "ext-openssl": "*"
+ },
"platform-overrides": {
"php": "8.0"
},
diff --git a/docker-compose.yml b/docker-compose.yml
index 80d626d9..6cb8400a 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -29,6 +29,8 @@ services:
- VONAGE_API_SECRET
- VONAGE_TO
- VONAGE_FROM
+ - DISCORD_WEBHOOK_ID
+ - DISCORD_WEBHOOK_TOKEN
build:
context: .
volumes:
diff --git a/docs/add-new-adapter.md b/docs/add-new-adapter.md
index a720bbc0..70d3d38d 100644
--- a/docs/add-new-adapter.md
+++ b/docs/add-new-adapter.md
@@ -81,10 +81,10 @@ Putting it all together, the `SendGrid` adapter should look like this:
```php
-
- ./tests/unit
-
-
- ./tests/e2e/
+
+ ./tests/
\ No newline at end of file
diff --git a/src/Utopia/Messaging/Adapter.php b/src/Utopia/Messaging/Adapter.php
index f616600b..6fdfc285 100644
--- a/src/Utopia/Messaging/Adapter.php
+++ b/src/Utopia/Messaging/Adapter.php
@@ -29,15 +29,30 @@ abstract public function getMaxMessagesPerRequest(): int;
*
* @param Message $message The message to send.
* @return string The response body.
+ *
+ * @throws \Exception
*/
- abstract public function send(Message $message): string;
+ public function send(Message $message): string
+ {
+ if (! \is_a($message, $this->getMessageType())) {
+ throw new \Exception('Invalid message type.');
+ }
+ if (\method_exists($message, 'getTo') && \count($message->getTo()) > $this->getMaxMessagesPerRequest()) {
+ throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request.");
+ }
+ if (! \method_exists($this, 'process')) {
+ throw new \Exception('Adapter does not implement process method.');
+ }
+
+ return $this->process($message);
+ }
/**
* Send an HTTP request.
*
* @param string $method The HTTP method to use.
* @param string $url The URL to send the request to.
- * @param array $headers An array of headers to send with the request.
+ * @param array $headers An array of headers to send with the request.
* @param string|null $body The body of the request.
* @return string The response body.
*
diff --git a/src/Utopia/Messaging/Adapter/Chat/Discord.php b/src/Utopia/Messaging/Adapter/Chat/Discord.php
new file mode 100644
index 00000000..7b0deea6
--- /dev/null
+++ b/src/Utopia/Messaging/Adapter/Chat/Discord.php
@@ -0,0 +1,82 @@
+getWait())) {
+ $query['wait'] = $message->getWait();
+ }
+ if (! \is_null($message->getThreadId())) {
+ $query['thread_id'] = $message->getThreadId();
+ }
+
+ $queryString = '';
+ foreach ($query as $key => $value) {
+ if (empty($queryString)) {
+ $queryString .= '?';
+ }
+ $queryString .= $key.'='.$value;
+ }
+
+ return $this->request(
+ method: 'POST',
+ url: "https://discord.com/api/webhooks/{$this->webhookId}/{$this->webhookToken}{$queryString}",
+ headers: [
+ 'Content-Type: application/json',
+ ],
+ body: \json_encode([
+ 'content' => $message->getContent(),
+ 'username' => $message->getUsername(),
+ 'avatar_url' => $message->getAvatarUrl(),
+ 'tts' => $message->getTTS(),
+ 'embeds' => $message->getEmbeds(),
+ 'allowed_mentions' => $message->getAllowedMentions(),
+ 'components' => $message->getComponents(),
+ 'attachments' => $message->getAttachments(),
+ 'flags' => $message->getFlags(),
+ 'thread_name' => $message->getThreadName(),
+ ]),
+ );
+ }
+}
diff --git a/src/Utopia/Messaging/Adapters/Email.php b/src/Utopia/Messaging/Adapter/Email.php
similarity index 50%
rename from src/Utopia/Messaging/Adapters/Email.php
rename to src/Utopia/Messaging/Adapter/Email.php
index 55318e46..9b395a0e 100644
--- a/src/Utopia/Messaging/Adapters/Email.php
+++ b/src/Utopia/Messaging/Adapter/Email.php
@@ -1,6 +1,6 @@
getMessageType())) {
- throw new \Exception('Invalid message type.');
- }
- if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) {
- throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request.");
- }
-
- return $this->process($message);
- }
-
/**
* Process an email message.
*
diff --git a/src/Utopia/Messaging/Adapters/Email/Mailgun.php b/src/Utopia/Messaging/Adapter/Email/Mailgun.php
similarity index 94%
rename from src/Utopia/Messaging/Adapters/Email/Mailgun.php
rename to src/Utopia/Messaging/Adapter/Email/Mailgun.php
index 09ad8895..b068814e 100644
--- a/src/Utopia/Messaging/Adapters/Email/Mailgun.php
+++ b/src/Utopia/Messaging/Adapter/Email/Mailgun.php
@@ -1,8 +1,8 @@
SMTPAuth = false;
$mail->Username = '';
$mail->Password = '';
- $mail->SMTPSecure = false;
+ $mail->SMTPSecure = '';
$mail->SMTPAutoTLS = false;
$mail->CharSet = 'UTF-8';
$mail->Subject = $message->getSubject();
@@ -54,6 +54,6 @@ protected function process(Email $message): string
throw new \Exception($mail->ErrorInfo);
}
- return true;
+ return \json_encode($message);
}
}
diff --git a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php b/src/Utopia/Messaging/Adapter/Email/Sendgrid.php
similarity index 93%
rename from src/Utopia/Messaging/Adapters/Email/Sendgrid.php
rename to src/Utopia/Messaging/Adapter/Email/Sendgrid.php
index 18dccc20..27be13bc 100644
--- a/src/Utopia/Messaging/Adapters/Email/Sendgrid.php
+++ b/src/Utopia/Messaging/Adapter/Email/Sendgrid.php
@@ -1,8 +1,8 @@
notify($message->getTo(), $payload));
}
+ /**
+ * @param array $to
+ * @param array $payload
+ * @return array
+ *
+ * @throws Exception
+ */
private function notify(array $to, array $payload): array
{
$headers = [
@@ -67,16 +74,16 @@ private function notify(array $to, array $payload): array
'apns-push-type: alert',
];
- $sh = curl_share_init();
+ $sh = \curl_share_init();
- curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
+ \curl_share_setopt($sh, CURLSHOPT_SHARE, CURL_LOCK_DATA_CONNECT);
- $ch = curl_init();
+ $ch = \curl_init();
- curl_setopt($ch, CURLOPT_SHARE, $sh);
- curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
+ \curl_setopt($ch, CURLOPT_SHARE, $sh);
+ \curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
- curl_setopt_array($ch, [
+ \curl_setopt_array($ch, [
CURLOPT_PORT => 443,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POST => true,
@@ -93,15 +100,15 @@ private function notify(array $to, array $payload): array
$endpoint = 'https://api.development.push.apple.com';
}
- $mh = curl_multi_init();
+ $mh = \curl_multi_init();
$handles = [];
// Create a handle for each request
foreach ($to as $token) {
- curl_setopt($ch, CURLOPT_URL, $endpoint.'/3/device/'.$token);
+ \curl_setopt($ch, CURLOPT_URL, $endpoint.'/3/device/'.$token);
- $handle = curl_copy_handle($ch);
- curl_multi_add_handle($mh, $handle);
+ $handle = \curl_copy_handle($ch);
+ \curl_multi_add_handle($mh, $handle);
$handles[] = $handle;
}
@@ -111,17 +118,17 @@ private function notify(array $to, array $payload): array
// Execute the handles
while ($active && $status == CURLM_OK) {
- $status = curl_multi_exec($mh, $active);
+ $status = \curl_multi_exec($mh, $active);
}
- // Check each handle's result
+ // Check each handles result
$responses = [];
foreach ($handles as $ch) {
- $urlInfo = curl_getinfo($ch);
+ $urlInfo = \curl_getinfo($ch);
$device = basename($urlInfo['url']); // Extracts deviceToken from the URL
- if (! curl_errno($ch)) {
- $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+ if (! \curl_errno($ch)) {
+ $statusCode = \curl_getinfo($ch, CURLINFO_HTTP_CODE);
$responses[] = [
'device' => $device,
'status' => 'success',
@@ -130,46 +137,20 @@ private function notify(array $to, array $payload): array
} else {
$responses[$device] = [
'status' => 'error',
- 'error' => curl_error($ch),
+ 'error' => \curl_error($ch),
];
}
- curl_multi_remove_handle($mh, $ch);
- curl_close($ch);
+ \curl_multi_remove_handle($mh, $ch);
+ \curl_close($ch);
}
- curl_multi_close($mh);
- curl_share_close($sh);
+ \curl_multi_close($mh);
+ \curl_share_close($sh);
return $responses;
}
- private function formatResponse(string $response): array
- {
- $filtered = array_filter(
- explode("\r\n", $response),
- function ($value) {
- return ! empty($value);
- }
- );
-
- $result = [];
-
- foreach ($filtered as $value) {
- if (str_contains($value, 'HTTP')) {
- $result['status'] = trim(str_replace('HTTP/2 ', '', $value));
-
- continue;
- }
-
- $parts = explode(':', trim($value));
-
- $result[$parts[0]] = $parts[1];
- }
-
- return $result;
- }
-
/**
* Generate JWT.
*
@@ -186,21 +167,21 @@ private function generateJwt(): string
// Replaces URL sensitive characters that could be the result of base64 encoding.
// Replace to _ to avoid any special handling.
- $base64UrlHeader = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
- $base64UrlClaims = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claims));
+ $base64UrlHeader = \str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
+ $base64UrlClaims = \str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($claims));
if (! $this->authKey) {
throw new \Exception('Invalid private key');
}
$signature = '';
- $success = openssl_sign("$base64UrlHeader.$base64UrlClaims", $signature, $this->authKey, OPENSSL_ALGO_SHA256);
+ $success = \openssl_sign("$base64UrlHeader.$base64UrlClaims", $signature, $this->authKey, OPENSSL_ALGO_SHA256);
if (! $success) {
throw new \Exception('Failed to sign JWT');
}
- $base64UrlSignature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
+ $base64UrlSignature = \str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
return "$base64UrlHeader.$base64UrlClaims.$base64UrlSignature";
}
diff --git a/src/Utopia/Messaging/Adapters/Push/FCM.php b/src/Utopia/Messaging/Adapter/Push/FCM.php
similarity index 94%
rename from src/Utopia/Messaging/Adapters/Push/FCM.php
rename to src/Utopia/Messaging/Adapter/Push/FCM.php
index 4a028f62..4625b905 100644
--- a/src/Utopia/Messaging/Adapters/Push/FCM.php
+++ b/src/Utopia/Messaging/Adapter/Push/FCM.php
@@ -1,8 +1,8 @@
+ */
+ protected array $localAdapters = [];
public function __construct(SMSAdapter $defaultAdapter)
{
@@ -34,6 +37,9 @@ public function setLocal(string $callingCode, SMSAdapter $adapter): self
return $this;
}
+ /**
+ * @return array
+ */
protected function filterCallingCodesByAdapter(SMSAdapter $adapter): array
{
$result = [];
@@ -77,6 +83,10 @@ protected function process(SMS $message): string
return \json_encode($results);
}
+ /**
+ * @param array $recipients
+ * @return array|SMSAdapter>
+ */
protected function getNextRecipientsAndAdapter(array $recipients): array
{
$nextRecipients = [];
@@ -97,7 +107,7 @@ protected function getNextRecipientsAndAdapter(array $recipients): array
protected function getAdapterByPhoneNumber(?string $phoneNumber): SMSAdapter
{
$callingCode = CallingCode::fromPhoneNumber($phoneNumber);
- if ($callingCode === null || empty($callingCode)) {
+ if (empty($callingCode)) {
return $this->defaultAdapter;
}
diff --git a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php b/src/Utopia/Messaging/Adapter/SMS/GEOSMS/CallingCode.php
similarity index 99%
rename from src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php
rename to src/Utopia/Messaging/Adapter/SMS/GEOSMS/CallingCode.php
index 141c9250..35e8fe0d 100644
--- a/src/Utopia/Messaging/Adapters/SMS/GEOSMS/CallingCode.php
+++ b/src/Utopia/Messaging/Adapter/SMS/GEOSMS/CallingCode.php
@@ -1,6 +1,6 @@
true,
];
- public static function fromPhoneNumber($number): ?string
+ public static function fromPhoneNumber(string $number): ?string
{
$digits = str_replace(['+', ' ', '(', ')', '-'], '', $number);
diff --git a/src/Utopia/Messaging/Adapters/SMS/Infobip.php b/src/Utopia/Messaging/Adapter/SMS/Infobip.php
similarity index 93%
rename from src/Utopia/Messaging/Adapters/SMS/Infobip.php
rename to src/Utopia/Messaging/Adapter/SMS/Infobip.php
index f18a62f2..f52e1079 100644
--- a/src/Utopia/Messaging/Adapters/SMS/Infobip.php
+++ b/src/Utopia/Messaging/Adapter/SMS/Infobip.php
@@ -1,8 +1,8 @@
$numbers
+ */
private function formatNumbers(array $numbers): string
{
$formatted = \array_map(
diff --git a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php b/src/Utopia/Messaging/Adapter/SMS/Telnyx.php
similarity index 91%
rename from src/Utopia/Messaging/Adapters/SMS/Telnyx.php
rename to src/Utopia/Messaging/Adapter/SMS/Telnyx.php
index 06b262d2..0a6b5827 100644
--- a/src/Utopia/Messaging/Adapters/SMS/Telnyx.php
+++ b/src/Utopia/Messaging/Adapter/SMS/Telnyx.php
@@ -1,8 +1,8 @@
getMessageType())) {
- throw new \Exception('Invalid message type.');
- }
- if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) {
- throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request.");
- }
-
- return $this->process($message);
- }
-
- /**
- * Send a push message.
- *
- * @param PushMessage $message Message to process.
- * @return string The response body.
- */
- abstract protected function process(PushMessage $message): string;
-}
diff --git a/src/Utopia/Messaging/Adapters/SMS.php b/src/Utopia/Messaging/Adapters/SMS.php
deleted file mode 100644
index 5a2b6c4e..00000000
--- a/src/Utopia/Messaging/Adapters/SMS.php
+++ /dev/null
@@ -1,45 +0,0 @@
-getMessageType())) {
- throw new \Exception('Invalid message type.');
- }
- if (\count($message->getTo()) > $this->getMaxMessagesPerRequest()) {
- throw new \Exception("{$this->getName()} can only send {$this->getMaxMessagesPerRequest()} messages per request.");
- }
-
- return $this->process($message);
- }
-
- /**
- * Send an SMS message.
- *
- * @param SMSMessage $message Message to send.
- * @return string The response body.
- */
- abstract protected function process(SMSMessage $message): string;
-}
diff --git a/src/Utopia/Messaging/Message.php b/src/Utopia/Messaging/Message.php
index 5c335d17..3b5e21ae 100644
--- a/src/Utopia/Messaging/Message.php
+++ b/src/Utopia/Messaging/Message.php
@@ -7,7 +7,4 @@
*/
interface Message
{
- public function getTo(): array;
-
- public function getFrom(): ?string;
}
diff --git a/src/Utopia/Messaging/Messages/Discord.php b/src/Utopia/Messaging/Messages/Discord.php
new file mode 100644
index 00000000..dffa5fec
--- /dev/null
+++ b/src/Utopia/Messaging/Messages/Discord.php
@@ -0,0 +1,102 @@
+|null $embeds
+ * @param array|null $allowedMentions
+ * @param array|null $components
+ * @param array|null $attachments
+ */
+ public function __construct(
+ private string $content,
+ private ?string $username = null,
+ private ?string $avatarUrl = null,
+ private ?bool $tts = null,
+ private ?array $embeds = null,
+ private ?array $allowedMentions = null,
+ private ?array $components = null,
+ private ?array $attachments = null,
+ private ?string $flags = null,
+ private ?string $threadName = null,
+ private ?bool $wait = null,
+ private ?string $threadId = null
+ ) {
+ }
+
+ public function getContent(): string
+ {
+ return $this->content;
+ }
+
+ public function getUsername(): ?string
+ {
+ return $this->username;
+ }
+
+ public function getAvatarUrl(): ?string
+ {
+ return $this->avatarUrl;
+ }
+
+ public function getTts(): ?bool
+ {
+ return $this->tts;
+ }
+
+ /**
+ * @return array|null
+ */
+ public function getEmbeds(): ?array
+ {
+ return $this->embeds;
+ }
+
+ /**
+ * @return array|null
+ */
+ public function getAllowedMentions(): ?array
+ {
+ return $this->allowedMentions;
+ }
+
+ /**
+ * @return array|null
+ */
+ public function getComponents(): ?array
+ {
+ return $this->components;
+ }
+
+ /**
+ * @return array|null
+ */
+ public function getAttachments(): ?array
+ {
+ return $this->attachments;
+ }
+
+ public function getFlags(): ?string
+ {
+ return $this->flags;
+ }
+
+ public function getThreadName(): ?string
+ {
+ return $this->threadName;
+ }
+
+ public function getWait(): ?bool
+ {
+ return $this->wait;
+ }
+
+ public function getThreadId(): ?string
+ {
+ return $this->threadId;
+ }
+}
diff --git a/src/Utopia/Messaging/Messages/Email.php b/src/Utopia/Messaging/Messages/Email.php
index 545b1d54..8e79c10c 100644
--- a/src/Utopia/Messaging/Messages/Email.php
+++ b/src/Utopia/Messaging/Messages/Email.php
@@ -7,11 +7,11 @@
class Email implements Message
{
/**
- * @param array $to The recipients of the email.
+ * @param array $to The recipients of the email.
* @param string $subject The subject of the email.
* @param string $content The content of the email.
* @param string|null $from The sender of the email.
- * @param array|null $attachments The attachments of the email.
+ * @param array|null $attachments The attachments of the email.
* @param bool $html Whether the message is HTML or not.
*/
public function __construct(
@@ -24,6 +24,9 @@ public function __construct(
) {
}
+ /**
+ * @return array
+ */
public function getTo(): array
{
return $this->to;
@@ -44,6 +47,9 @@ public function getFrom(): ?string
return $this->from;
}
+ /**
+ * @return array|null
+ */
public function getAttachments(): ?array
{
return $this->attachments;
diff --git a/src/Utopia/Messaging/Messages/Push.php b/src/Utopia/Messaging/Messages/Push.php
index 337d0fbd..bf1712f6 100644
--- a/src/Utopia/Messaging/Messages/Push.php
+++ b/src/Utopia/Messaging/Messages/Push.php
@@ -7,10 +7,10 @@
class Push implements Message
{
/**
- * @param array $to The recipients of the push notification.
+ * @param array $to The recipients of the push notification.
* @param string $title The title of the push notification.
* @param string $body The body of the push notification.
- * @param array|null $data This parameter specifies the custom key-value pairs of the message's payload. For example, with data:{"score":"3x1"}:
On Apple platforms, if the message is sent via APNs, it represents the custom data fields. If it is sent via FCM, it would be represented as key value dictionary in AppDelegate application:didReceiveRemoteNotification:.
On Android, this would result in an intent extra named score with the string value 3x1.
The key should not be a reserved word ("from", "message_type", or any word starting with "google" or "gcm"). Do not use any of the words defined in this table (such as collapse_key).
Values in string types are recommended. You have to convert values in objects or other non-string data types (e.g., integers or booleans) to string.
+ * @param array|null $data This parameter specifies the custom key-value pairs of the message's payload. For example, with data:{"score":"3x1"}:
On Apple platforms, if the message is sent via APNs, it represents the custom data fields. If it is sent via FCM, it would be represented as key value dictionary in AppDelegate application:didReceiveRemoteNotification:.
On Android, this would result in an intent extra named score with the string value 3x1.
The key should not be a reserved word ("from", "message_type", or any word starting with "google" or "gcm"). Do not use any of the words defined in this table (such as collapse_key).
Values in string types are recommended. You have to convert values in objects or other non-string data types (e.g., integers or booleans) to string.
* @param string|null $sound The sound to play when the device receives the notification.
On Android, sound files must reside in /res/raw/.
On iOS, sounds files must reside in the main bundle of the client app or in the Library/Sounds folder of the app's data container.
* @param string|null $action The action associated with a user click on the notification.
On Android, this is the activity to launch.
On iOS, this is the category to launch.
* @param string|null $icon Android only. The icon of the push notification. Sets the notification icon to myicon for drawable resource myicon. If you don't send this key in the request, FCM displays the launcher icon specified in your app manifest.
@@ -32,6 +32,9 @@ public function __construct(
) {
}
+ /**
+ * @return array
+ */
public function getTo(): array
{
return $this->to;
@@ -52,6 +55,9 @@ public function getBody(): string
return $this->body;
}
+ /**
+ * @return array|null
+ */
public function getData(): ?array
{
return $this->data;
diff --git a/src/Utopia/Messaging/Messages/SMS.php b/src/Utopia/Messaging/Messages/SMS.php
index 31be8d99..a2eb2bad 100644
--- a/src/Utopia/Messaging/Messages/SMS.php
+++ b/src/Utopia/Messaging/Messages/SMS.php
@@ -6,6 +6,10 @@
class SMS implements Message
{
+ /**
+ * @param array $to
+ * @param array|null $attachments
+ */
public function __construct(
private array $to,
private string $content,
@@ -14,6 +18,9 @@ public function __construct(
) {
}
+ /**
+ * @return array
+ */
public function getTo(): array
{
return $this->to;
@@ -29,6 +36,9 @@ public function getFrom(): ?string
return $this->from;
}
+ /**
+ * @return array|null
+ */
public function getAttachments(): ?array
{
return $this->attachments;
diff --git a/tests/e2e/Base.php b/tests/Messaging/Adapter/Base.php
similarity index 82%
rename from tests/e2e/Base.php
rename to tests/Messaging/Adapter/Base.php
index 14970e51..218cadd9 100644
--- a/tests/e2e/Base.php
+++ b/tests/Messaging/Adapter/Base.php
@@ -1,11 +1,14 @@
+ */
protected function getLastRequest(): array
{
\sleep(2);
@@ -16,6 +19,9 @@ protected function getLastRequest(): array
return $request;
}
+ /**
+ * @return array
+ */
protected function getLastEmail(): array
{
sleep(3);
diff --git a/tests/Messaging/Adapter/Chat/DiscordTest.php b/tests/Messaging/Adapter/Chat/DiscordTest.php
new file mode 100644
index 00000000..ee7df927
--- /dev/null
+++ b/tests/Messaging/Adapter/Chat/DiscordTest.php
@@ -0,0 +1,33 @@
+send($message), true);
+
+ $this->assertNotEmpty($result);
+ $this->assertNotEmpty($result['id']);
+ }
+}
diff --git a/tests/e2e/Email/EmailTest.php b/tests/Messaging/Adapter/Email/EmailTest.php
similarity index 84%
rename from tests/e2e/Email/EmailTest.php
rename to tests/Messaging/Adapter/Email/EmailTest.php
index f72fe37e..f0064acd 100644
--- a/tests/e2e/Email/EmailTest.php
+++ b/tests/Messaging/Adapter/Email/EmailTest.php
@@ -1,17 +1,17 @@
send($message));
+ $result = \json_decode($sender->send($message), true);
$this->assertArrayHasKey('id', $result);
$this->assertArrayHasKey('message', $result);
- $this->assertTrue(str_contains(strtolower($result['message']), 'queued'));
+ $this->assertTrue(\str_contains(\strtolower($result['message']), 'queued'));
}
}
diff --git a/tests/e2e/Email/SendgridTest.php b/tests/Messaging/Adapter/Email/SendgridTest.php
similarity index 73%
rename from tests/e2e/Email/SendgridTest.php
rename to tests/Messaging/Adapter/Email/SendgridTest.php
index d2b5ea00..58c10b66 100644
--- a/tests/e2e/Email/SendgridTest.php
+++ b/tests/Messaging/Adapter/Email/SendgridTest.php
@@ -1,32 +1,32 @@
send($message);
diff --git a/tests/e2e/Push/APNSTest.php b/tests/Messaging/Adapter/Push/APNSTest.php
similarity index 61%
rename from tests/e2e/Push/APNSTest.php
rename to tests/Messaging/Adapter/Push/APNSTest.php
index 335449ca..dbbf6874 100644
--- a/tests/e2e/Push/APNSTest.php
+++ b/tests/Messaging/Adapter/Push/APNSTest.php
@@ -1,25 +1,24 @@
assertEquals(CallingCode::NORTH_AMERICA, CallingCode::fromPhoneNumber('+11234567890'));
$this->assertEquals(CallingCode::INDIA, CallingCode::fromPhoneNumber('+911234567890'));
diff --git a/tests/e2e/SMS/GEOSMSTest.php b/tests/Messaging/Adapter/SMS/GEOSMSTest.php
similarity index 88%
rename from tests/e2e/SMS/GEOSMSTest.php
rename to tests/Messaging/Adapter/SMS/GEOSMSTest.php
index f6e08801..d10b7799 100644
--- a/tests/e2e/SMS/GEOSMSTest.php
+++ b/tests/Messaging/Adapter/SMS/GEOSMSTest.php
@@ -1,16 +1,16 @@
createMock(SMSAdapter::class);
$defaultAdapterMock->method('getName')
@@ -35,7 +35,7 @@ public function testSendSMSUsingDefaultAdapter()
$this->assertEquals('success', $result['default']['status']);
}
- public function testSendSMSUsingLocalAdapter()
+ public function testSendSMSUsingLocalAdapter(): void
{
$defaultAdapterMock = $this->createMock(SMSAdapter::class);
$localAdapterMock = $this->createMock(SMSAdapter::class);
@@ -62,7 +62,7 @@ public function testSendSMSUsingLocalAdapter()
$this->assertEquals('success', $result['local']['status']);
}
- public function testSendSMSUsingLocalAdapterAndDefault()
+ public function testSendSMSUsingLocalAdapterAndDefault(): void
{
$defaultAdapterMock = $this->createMock(SMSAdapter::class);
$defaultAdapterMock->method('getName')
@@ -94,7 +94,7 @@ public function testSendSMSUsingLocalAdapterAndDefault()
$this->assertEquals('success', $result['default']['status']);
}
- public function testSendSMSUsingGroupedLocalAdapter()
+ public function testSendSMSUsingGroupedLocalAdapter(): void
{
$defaultAdapterMock = $this->createMock(SMSAdapter::class);
$localAdapterMock = $this->createMock(SMSAdapter::class);
diff --git a/tests/Messaging/Adapter/SMS/Msg91Test.php b/tests/Messaging/Adapter/SMS/Msg91Test.php
new file mode 100644
index 00000000..165dd23a
--- /dev/null
+++ b/tests/Messaging/Adapter/SMS/Msg91Test.php
@@ -0,0 +1,29 @@
+send($message);
+ // $result = \json_decode($response, true);
+
+ // $this->assertEquals('success', $result['type']);
+
+ $this->markTestSkipped('Msg91 requires business verification to use template and SMS api.');
+ }
+}
diff --git a/tests/e2e/SMS/SMSTest.php b/tests/Messaging/Adapter/SMS/SMSTest.php
similarity index 86%
rename from tests/e2e/SMS/SMSTest.php
rename to tests/Messaging/Adapter/SMS/SMSTest.php
index 6e233eea..848b034a 100644
--- a/tests/e2e/SMS/SMSTest.php
+++ b/tests/Messaging/Adapter/SMS/SMSTest.php
@@ -1,17 +1,17 @@
markTestSkipped('Telesign requires support/sales call in order to enable bulk SMS');
}
diff --git a/tests/e2e/SMS/TelnyxTest.php b/tests/Messaging/Adapter/SMS/TelnyxTest.php
similarity index 68%
rename from tests/e2e/SMS/TelnyxTest.php
rename to tests/Messaging/Adapter/SMS/TelnyxTest.php
index def2f949..3db276a5 100644
--- a/tests/e2e/SMS/TelnyxTest.php
+++ b/tests/Messaging/Adapter/SMS/TelnyxTest.php
@@ -1,19 +1,17 @@
send($message);
diff --git a/tests/e2e/SMS/Msg91Test.php b/tests/e2e/SMS/Msg91Test.php
deleted file mode 100644
index c066343c..00000000
--- a/tests/e2e/SMS/Msg91Test.php
+++ /dev/null
@@ -1,30 +0,0 @@
-setTemplate(getenv('MSG_91_FROM'));
-
- $message = new SMS(
- to: [getenv('MSG_91_TO')],
- content: 'Test Content',
- );
-
- $response = $sender->send($message);
- $result = \json_decode($response, true);
-
- $this->assertEquals('success', $result['type']);
- $this->assertNotEmpty($result['message']);
- }
-}
diff --git a/tests/unit/.gitkeep b/tests/unit/.gitkeep
deleted file mode 100644
index e69de29b..00000000