chore(messaging): absorb utopia-php/messaging#67
Conversation
feat: geosms adapter
# Conflicts: # src/Utopia/Messaging/Adapter/SMS/GEOSMS.php # src/Utopia/Messaging/Adapter/SMS/GEOSMS/CallingCode.php # tests/Messaging/Adapter/Email/SendgridTest.php # tests/Messaging/Adapter/SMS/GEOSMS/CallingCodeTest.php # tests/Messaging/Adapter/SMS/GEOSMSTest.php
feat: add sms from override to constructor
…eat-uniform-response
Use default false bool sandbox instead of endpoint param
# Conflicts: # composer.json # composer.lock # src/Utopia/Messaging/Adapter/Push/APNS.php # src/Utopia/Messaging/Messages/Email.php # src/Utopia/Messaging/Messages/Push.php # src/Utopia/Messaging/Messages/SMS.php # tests/Messaging/Adapter/Email/EmailTest.php # tests/Messaging/Adapter/Email/MailgunTest.php # tests/Messaging/Adapter/Email/SendgridTest.php # tests/Messaging/Adapter/Push/APNSTest.php # tests/Messaging/Adapter/Push/FCMTest.php # tests/Messaging/Adapter/SMS/GEOSMS/CallingCodeTest.php # tests/Messaging/Adapter/SMS/GEOSMSTest.php # tests/Messaging/Adapter/SMS/Msg91Test.php # tests/Messaging/Adapter/SMS/SMSTest.php # tests/Messaging/Adapter/SMS/TelesignTest.php # tests/Messaging/Adapter/SMS/TelnyxTest.php # tests/Messaging/Adapter/SMS/TwilioTest.php # tests/Messaging/Adapter/SMS/VonageTest.php
Add messaging send telemetry
Add MSG91 metadata tracking
(feat): surface transport error details in FCM push results
Adapter::request() now builds PSR-7 requests via utopia-php/psr7's Request\Factory and sends them through the client's cURL adapter. Adapter::requestMulti() fans out over Swoole coroutines with a bounded Utopia\Client\Pool instead of curl_multi + HTTP/2 multiplexing. Both keep the legacy result array shape so adapters and tests are unaffected. Also: PHP >= 8.5 and ext-swoole required, Mailgun attachments use multipart Part::file, unused Adapter::getCountryCode() removed along with the libphonenumber dependency, phpstan upgraded to 2.x, and the test image switched to appwrite/utopia-base (ships Swoole, no io_uring).
…rors APNs only accepts HTTP/2, which Swoole's Coroutine\Http\Client cannot negotiate (connection reset). The requestMulti() pool now uses the client's cURL adapter with CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_2_0; Swoole's native-curl hook (enabled by Coroutine\run and by Appwrite's runtime) keeps sends concurrent per coroutine. APNS error extraction now falls back to the transport error or 'Unknown error' instead of passing null to Response::addResult().
Adapter now takes an optional Psr\Http\Client\ClientInterface (constructor param + setClient(), mirroring the telemetry pattern). Consumers can inject any PSR-18 implementation — pooled/retry-decorated utopia clients, or an in-memory mock for network-free tests. When none is injected, the previous defaults are built internally (HTTP/2 cURL adapter; pooled for requestMulti). The User-Agent moved from client config onto the request so injected clients send the same identity. Injected clients must negotiate HTTP/2 for APNs (documented on the constructor).
… docblock requestMulti() uses null-coalescing instead of the elvis operator so an explicit empty-array body is still sent; the result shape docblocks now declare error as string since null is never produced.
Adapter now takes (Closure(): ClientInterface)|null $clientFactory (constructor param + setClientFactory()) instead of a single ClientInterface. requestMulti() always pools internally, calling the factory once per pooled connection — so consumers describe how to build one client and the adapter owns concurrency, removing the inject-a-Pool-or-serialize caveat. The pool is consumed via Pools\Pool::use() directly since consumer factories only promise PSR-18, not the streaming interface Utopia\Client\Pool requires.
(feat): replace raw curl transport with utopia-php/client
Strip hoisted QA tooling, replace library CI with the mirror redirect workflow, and normalise composer.json (unit/e2e script split, direct utopia-php/pools dependency, prefer-stable). Test contract: unit tier runs network-free (GEOSMS, CallingCode, Telemetry, SES/Resend routing, SES signing); e2e tier runs host-side against compose services (mailcatcher 11025/11080, request-catcher 15000). The in-container test runner (Dockerfile, tests service) and the 15 provider tests requiring org secrets are deleted; the Email Mock adapter gains host/port constructor params so tests can target the host-mapped ports. Fixes on the way in: Discord webhook query string built with http_build_query (multiple params were previously joined without '&'); expectation-less mocks converted to stubs (PHPUnit 12 notices). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Greptile SummaryThis PR absorbs the
Confidence Score: 4/5Safe to merge pending fixes to Sendgrid and Mailgun attachment handling. The Sendgrid adapter passes the raw false return of file_get_contents() directly into base64_encode(), which is a TypeError on PHP 8.5 (the minimum required version). The Mailgun adapter silently treats an unreadable file as 0 bytes and truncates its own error message. Every other adapter in the PR handles these cases correctly, making these two outliers clearly unintentional gaps. Sendgrid.php and Mailgun.php: both attachment-handling paths need filesize() false-return guards, in-memory content checks, and (for Sendgrid) a file_get_contents() false-return guard. Important Files Changed
Reviews (2): Last reviewed commit: "fix(messaging): address review findings" | Re-trigger Greptile |
- FCM: throw a meaningful exception when the Google token request fails instead of fataling on a null response - SMTP: check filesize/file_get_contents for false before use (matches the SES pattern) - APNS: process() protected like every other adapter - Adapter: requestMulti no longer reads bodies[0] when bodies is empty Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Absorbs utopia-php/messaging with full history via
bin/monorepo absorb.Changes on the way in
mirror.ymlPR-redirect + README banner added; mirror ruleset normalised (classic-protection app bypass already applied).composer test= network-free unit tier (41 tests);composer test:e2e= host-run against compose services — mailcatcher (11025/11080) and request-catcher (15000). The in-container test runner (Dockerfile +testscompose service) and the 15 provider tests requiring org secrets are deleted, per the storage precedent. The Email Mock adapter gains backward-compatiblehost/portconstructor params so tests can target host-mapped ports.prefer-stable, and a directutopia-php/pools ^1.0dependency (src usesUtopia\Pools\Adapter\Swooledirectly but previously only received pools transitively via client).http_build_query— multiple params were previously concatenated without&.Net −3,425 LoC.
🤖 Generated with Claude Code