Skip to content

feat: add Vonage multi-channel Messages adapter (#8139)#110

Open
deepshekhardas wants to merge 1 commit into
utopia-php:mainfrom
deepshekhardas:feat/8139-vonage-messages-adapter
Open

feat: add Vonage multi-channel Messages adapter (#8139)#110
deepshekhardas wants to merge 1 commit into
utopia-php:mainfrom
deepshekhardas:feat/8139-vonage-messages-adapter

Conversation

@deepshekhardas

@deepshekhardas deepshekhardas commented Mar 16, 2026

Copy link
Copy Markdown

Adds a Vonage multi-channel Messages adapter supporting SMS, WhatsApp, Viber, and MMS.

Changes

  • New \VonageTrait\ with shared HTTP transport (\src/Utopia/Messaging/Adapter/VonageTrait.php)
  • New SMS adapter: \VonageMessages\ (\src/Utopia/Messaging/Adapter/SMS/VonageMessages.php)
  • New WhatsApp adapter: \Vonage\ (\src/Utopia/Messaging/Adapter/WhatsApp/Vonage.php)
  • New Viber adapter: \Vonage\ (\src/Utopia/Messaging/Adapter/Viber/Vonage.php)
  • New MMS adapter: \Vonage\ (\src/Utopia/Messaging/Adapter/MMS/Vonage.php)
  • Abstract \MMS\ adapter class (\src/Utopia/Messaging/Adapter/MMS.php)
  • Abstract \Viber\ adapter class (\src/Utopia/Messaging/Adapter/Viber.php)
  • Abstract \WhatsApp\ adapter class (\src/Utopia/Messaging/Adapter/WhatsApp.php)
  • Tests for the Vonage Messages SMS adapter

Testing

  • Unit tests added for VonageMessages adapter
  • Follows existing adapter patterns (Telnyx, Mock, etc.)

Closes #8139

@coderabbitai

coderabbitai Bot commented Mar 16, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@deepshekhardas has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 29 minutes and 8 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7a7c8cc9-e56f-4b5b-b848-bdb8839131d9

📥 Commits

Reviewing files that changed from the base of the PR and between fcb4c3c and ba22934.

📒 Files selected for processing (9)
  • src/Utopia/Messaging/Adapter/MMS.php
  • src/Utopia/Messaging/Adapter/MMS/Vonage.php
  • src/Utopia/Messaging/Adapter/SMS/VonageMessages.php
  • src/Utopia/Messaging/Adapter/Viber.php
  • src/Utopia/Messaging/Adapter/Viber/Vonage.php
  • src/Utopia/Messaging/Adapter/VonageTrait.php
  • src/Utopia/Messaging/Adapter/WhatsApp.php
  • src/Utopia/Messaging/Adapter/WhatsApp/Vonage.php
  • tests/Messaging/Adapter/SMS/VonageMessagesTest.php
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can generate walkthrough in a markdown collapsible section to save space.

Enable the reviews.collapse_walkthrough setting to generate walkthrough in a markdown collapsible section.

@deepshekhardas deepshekhardas force-pushed the feat/8139-vonage-messages-adapter branch from ba22934 to d623ac7 Compare June 2, 2026 01:54
@deepshekhardas

Copy link
Copy Markdown
Author

Rebased onto latest main. Could you please review? 🙏

@greptile-apps

greptile-apps Bot commented Jun 2, 2026

Copy link
Copy Markdown

Greptile Summary

  • Adds a shared Vonage Messages transport trait with JWT authentication.
  • Introduces Vonage adapters for SMS, WhatsApp, Viber, and MMS channels.
  • Adds abstract adapter types for WhatsApp, Viber, and MMS.
  • Adds unit coverage for the new Vonage Messages SMS adapter and related channel flows.

Confidence Score: 4/5

The new Vonage adapters are generally scoped, but the shared constructor path needs attention before merge because normal sends can fail after a successful provider response.

Focused coverage exists for the SMS adapter and the review isolated issues in the shared Vonage transport path rather than broad architectural uncertainty.

src/Utopia/Messaging/Adapter/VonageTrait.php

T-Rex T-Rex Logs

What T-Rex did

  • Ran a focused PHP harness to reproduce the base telemetry initialization failure in VonageMessages, which reached the mocked response path and then failed with a fatal error about sendCounter not being initialized.
  • Extended the harness to intercept VonageTrait headers and observed HTTP 202 Accepted with headers captured as complete colon-delimited strings, i.e., the issue was not reproduced.
  • Checked the adapter surface by loading on head; the load failed with Trait not found, indicating the multi-channel API surface is not available.
  • Analyzed channel payload checks; before harness, payload classes were missing, and after harness, a fatal trait not found prevented capturing any payloads or success response arrays.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (2)

  1. General comment

    P1 SMS VonageMessages adapter cannot autoload because it references the trait in the wrong namespace

    • Bug
      • The new Utopia\Messaging\Adapter\SMS\VonageMessages class fails during autoload with Trait "Utopia\Messaging\Adapter\SMS\VonageTrait" not found. This prevents the requested adapter surface check from proceeding to instantiate adapters or read metadata on head, so consumers cannot safely use the new SMS Vonage Messages adapter class.
    • Cause
      • src/Utopia/Messaging/Adapter/SMS/VonageMessages.php uses VonageTrait inside the Utopia\Messaging\Adapter\SMS namespace without importing the actual trait Utopia\Messaging\Adapter\VonageTrait. The WhatsApp, Viber, and MMS adapters include use Utopia\Messaging\Adapter\VonageTrait;, but the SMS adapter does not.
    • Fix
      • Add use Utopia\Messaging\Adapter\VonageTrait; to src/Utopia/Messaging/Adapter/SMS/VonageMessages.php or fully qualify the trait reference, then rerun the class surface/metadata check.

    T-Rex Ran code and verified through T-Rex

  2. General comment

    P1 SMS VonageMessages adapter references VonageTrait in the wrong namespace

    • Bug
      • Loading Utopia\Messaging\Adapter\SMS\VonageMessages fatals with Trait "Utopia\Messaging\Adapter\SMS\VonageTrait" not found, so the new SMS Messages adapter cannot be instantiated or exercised. This blocks the claimed multi-channel payload construction path before any request body can be built.
    • Cause
      • src/Utopia/Messaging/Adapter/SMS/VonageMessages.php uses VonageTrait inside namespace Utopia\Messaging\Adapter\SMS but does not import the actual trait from Utopia\Messaging\Adapter\VonageTrait. PHP therefore resolves it as Utopia\Messaging\Adapter\SMS\VonageTrait, which does not exist.
    • Fix
      • Add use Utopia\Messaging\Adapter\VonageTrait; to src/Utopia/Messaging/Adapter/SMS/VonageMessages.php (and remove any unused imports left over there) so use VonageTrait; resolves to the shared trait.

    T-Rex Ran code and verified through T-Rex

Reviews (2): Last reviewed commit: "feat: add Vonage multi-channel Messages ..." | Re-trigger Greptile

Comment thread src/Utopia/Messaging/Adapter/SMS/VonageMessages.php
Comment on lines +37 to +45

// This assumes the mock server returns a success response
// In a real environment, we'd check the request-catcher data
$this->assertNotEmpty($result);
}

public function testSendWhatsApp(): void
{
$sender = new VonageWhatsApp($this->applicationId, $this->privateKey);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 setEndpoint() is undefined on these adapters. None of VonageMessages, VonageWhatsApp, VonageViber, or VonageMMS define a setEndpoint() method — it only exists on Mock. Every test method in this class will crash with "Call to undefined method" before reaching any assertions. The same issue occurs in all four test methods (testSendSMS, testSendWhatsApp, testSendViber, testSendMMS). Either add setEndpoint() / getEndpoint() to VonageTrait, or use an environment variable / constructor parameter to override the base URL.

Comment on lines +43 to +45
public function testSendWhatsApp(): void
{
$sender = new VonageWhatsApp($this->applicationId, $this->privateKey);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 json_decode receives an array, not a string. send() returns array, so \json_decode($response, true) is called with an array argument. In PHP 8 this causes a TypeError; in earlier versions it silently returns null, making assertNotEmpty($result) fail. The same pattern is repeated in all four test methods. Either call send() directly and use assertResponse() (already defined in Base), or cast to JSON before decoding.

Comment thread src/Utopia/Messaging/Adapter/VonageTrait.php
@deepshekhardas deepshekhardas force-pushed the feat/8139-vonage-messages-adapter branch from d623ac7 to 4448c62 Compare June 17, 2026 09:19
Comment on lines +16 to +21
public function __construct(
private string $applicationId,
private string $privateKey,
private ?string $from = null
) {
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Initialize base telemetry. The trait constructor replaces Adapter::__construct() but never calls it, so the base class private $sendCounter property stays uninitialized. A normal new VonageMessages(...)->send($message) reaches Adapter::recordResponse() after process() returns, then reads $this->sendCounter and fails with Typed property Utopia\Messaging\Adapter::$sendCounter must not be accessed before initialization unless callers manually call setTelemetry() first.

Artifacts

Repro: focused PHP harness for VonageMessages send without initialized telemetry

  • Contains supporting evidence from the run (text/x-php; charset=utf-8).

Stack trace captured during the T-Rex run

  • Keeps the raw stack trace available without making the summary code-heavy.

View artifacts

T-Rex Ran code and verified through T-Rex

Comment on lines +51 to +55
headers: [
'Content-Type: application/json',
'Authorization: Bearer ' . $jwt,
'Accept: application/json',
],

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Use header strings. Adapter::request() expects headers as a list of complete header strings and passes the same array to CURLOPT_HTTPHEADER. This associative array can send malformed headers to cURL, so the Vonage request may miss a valid Authorization or Content-Type header.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant