feat: add media header support for button reply, template, and CTA URL messages#235
feat: add media header support for button reply, template, and CTA URL messages#235Vishwaraj123 wants to merge 3 commits intonetflie:developmentfrom
Conversation
…th new components and request handlers.
There was a problem hiding this comment.
Pull request overview
Adds richer header/media support to interactive Button Reply messages and CTA URL headers, plus extends template requests to support an additional “marketing messages” endpoint and a carousel component.
Changes:
- Add new header value objects for Button Reply (text/image/video/document) and CTA URL (video/document).
- Update request/message building to accept header objects for button replies and append template carousel components.
- Add optional
/marketing_messagesendpoint support for template sending via a new$use_mm_liteflag.
Reviewed changes
Copilot reviewed 17 out of 17 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/WhatsAppCloudApi.php | Extends sendTemplate() with $use_mm_lite and updates sendButton() to accept header objects (or strings mapped to TextHeader). |
| src/Request/MessageRequest.php | Adds use_mm_lite flag and switches node path to /marketing_messages when enabled. |
| src/Request/MessageRequest/RequestTemplateMessage.php | Appends carousel data into template.components. |
| src/Message/TemplateMessage.php | Exposes carousel() data from template components. |
| src/Message/Template/Component.php | Adds storage/accessor for carousel component data. |
| src/Request/MessageRequest/RequestButtonReplyMessage.php | Uses message-provided header body and marks request class final. |
| src/Message/ButtonReplyMessage.php | Changes button message header type to an object-backed header and marks message class final. |
| src/Message/ButtonReply/Header.php | Introduces abstract base for Button Reply headers. |
| src/Message/ButtonReply/TextHeader.php | Implements text header body for Button Reply. |
| src/Message/ButtonReply/ImageHeader.php | Implements image header body for Button Reply (MediaID-based). |
| src/Message/ButtonReply/VideoHeader.php | Implements video header body for Button Reply (MediaID-based). |
| src/Message/ButtonReply/DocumentHeader.php | Implements document header body for Button Reply (MediaID + filename). |
| src/Message/CtaUrl/VideoHeader.php | Adds CTA URL video header (link-based). |
| src/Message/CtaUrl/DocumentHeader.php | Adds CTA URL document header (MediaID + filename). |
| src/WebHook/Notification/Support/Referral.php | Removes ctwa_clid from referral support object. |
| src/WebHook/Notification/MessageNotificationFactory.php | Stops passing ctwa_clid when constructing Referral. |
| README.md | Documents new header options for CTA URL and Button Reply messages. |
Comments suppressed due to low confidence (1)
src/WhatsAppCloudApi.php:369
sendButton()now accepts an untyped$headerbut only supportsstring|null|ButtonReply\\Headerat runtime. Add a PHPDoc@paramwith the supported types and update the exception message to useButtonHeader::class(or similar) instead of a hard-coded class string, to avoid drift during refactors.
public function sendButton(string $to, string $body, ButtonAction $action, $header = null, ?string $footer = null): Response
{
if (is_string($header)) {
$header = new TextHeader($header);
}
if (!$header instanceof ButtonHeader && $header !== null) {
throw new InvalidMessage('Header must be instance of Netflie\WhatsAppCloudApi\Message\ButtonReply\Header if not left null');
}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if ($this->message->carousel()) { | ||
| $carousel = $this->message->carousel(); | ||
| $body['template']['components'][] = $carousel; | ||
| } |
There was a problem hiding this comment.
RequestTemplateMessage::body() now appends carousel data into template.components, but there are no unit tests covering the new carousel behavior (including how it should be shaped/merged into components). Please add/update tests to lock in the expected request payload when a carousel is present.
| use Netflie\WhatsAppCloudApi\Request\MessageRequest; | ||
|
|
||
| class RequestButtonReplyMessage extends MessageRequest | ||
| final class RequestButtonReplyMessage extends MessageRequest |
There was a problem hiding this comment.
This class is changed to final, which is a backwards-incompatible change for any consumers extending it. If there’s no strong need to prevent inheritance, consider leaving it non-final (or documenting this as a major-version change).
| final class RequestButtonReplyMessage extends MessageRequest | |
| class RequestButtonReplyMessage extends MessageRequest |
| @@ -26,9 +27,9 @@ public function __construct(string $to, string $body, ButtonAction $action, ?str | |||
| parent::__construct($to, $reply_to); | |||
| } | |||
|
|
|||
| public function header(): ?string | |||
| public function header(): ?array | |||
| { | |||
| return $this->header; | |||
| return $this->header ? $this->header->getBody() : null; | |||
| } | |||
There was a problem hiding this comment.
PR description claims “No breaking changes”, but this diff removes public API surface (e.g., Referral::ctwaClid() and changes ButtonReplyMessage public signatures/types). Please either restore backwards compatibility or update the PR description/changelog to reflect the breaking changes.
| protected $use_mm_lite; | ||
|
|
||
| public function __construct(Message $message, string $access_token, string $from_phone_number_id, ?int $timeout = null) | ||
| public function __construct(Message $message, string $access_token, string $from_phone_number_id, ?int $timeout = null, $use_mm_lite = false) | ||
| { | ||
| $this->message = $message; | ||
| $this->from_phone_number_id = $from_phone_number_id; | ||
| $this->use_mm_lite = $use_mm_lite; |
There was a problem hiding this comment.
$use_mm_lite is stored as an untyped property/parameter, so non-boolean truthy values (e.g. the string "false") will still switch the node path to /marketing_messages. Since this flag controls the endpoint, it should be strictly typed as bool (property and constructor param) and/or explicitly cast to bool when assigned.
| * @link https://developers.facebook.com/docs/whatsapp/api/messages/message-templates#supported-languages See language codes supported. | ||
| * @return Response | ||
| * | ||
| * @throws Response\ResponseException | ||
| */ | ||
| public function sendTemplate(string $to, string $template_name, string $language = 'en_US', ?Component $components = null): Response | ||
| public function sendTemplate(string $to, string $template_name, string $language = 'en_US', ?Component $components = null, $use_mm_lite = false): Response | ||
| { | ||
| $message = new Message\TemplateMessage($to, $template_name, $language, $components, $this->reply_to); | ||
| $request = new Request\MessageRequest\RequestTemplateMessage( | ||
| $message, | ||
| $this->app->accessToken(), | ||
| $this->app->fromPhoneNumberId(), | ||
| $this->timeout | ||
| $this->timeout, | ||
| $use_mm_lite |
There was a problem hiding this comment.
sendTemplate() introduces $use_mm_lite without a bool type and without documenting it in the PHPDoc. Because this ultimately changes the request endpoint, please type it as bool and document what it does (when to use /marketing_messages vs /messages).
| @@ -26,9 +27,9 @@ public function __construct(string $to, string $body, ButtonAction $action, ?str | |||
| parent::__construct($to, $reply_to); | |||
| } | |||
|
|
|||
| public function header(): ?string | |||
| public function header(): ?array | |||
| { | |||
| return $this->header; | |||
| return $this->header ? $this->header->getBody() : null; | |||
| } | |||
There was a problem hiding this comment.
ButtonReplyMessage is now final, its constructor changes $header from ?string to ?Header, and header() changes its return type from ?string to ?array. These are backwards-incompatible changes for any consumers instantiating/extending this message directly (and contradict the PR note about “No breaking changes”). Consider keeping the previous API (or adding new methods/types and deprecating the old ones) instead of changing the public signature/return types.
| @@ -30,8 +28,7 @@ public function __construct( | |||
| string $body, | |||
| string $media_type, | |||
| string $media_url, | |||
| string $thumbnail_url, | |||
| string $ctwa_clid | |||
| string $thumbnail_url | |||
| ) { | |||
There was a problem hiding this comment.
Referral drops the ctwa_clid constructor parameter and removes the ctwaClid() accessor. This is a breaking change for webhook consumers relying on that referral field. If the platform no longer sends ctwa_clid, consider keeping the property/accessor as nullable (or deprecating first) rather than removing it outright.
Adds media support for Button Reply, Template, and CTA URL message types.
This includes new frontend components and corresponding request handlers to process and store these messages.