From ea91ad05c985b852b1ba718d3d737c6e54e55bec Mon Sep 17 00:00:00 2001 From: James Seconde Date: Wed, 22 Mar 2023 12:28:54 +0000 Subject: [PATCH] New Message Types (#388) * PHP8: remove frivolous docblocks * Added two new files types for viber * Added new whatsapp sticker type * Tests for ViberVideo * dynamic property --- src/Messages/Channel/BaseMessage.php | 1 + .../MessageObjects/ViberActionObject.php | 38 +++++ src/Messages/Channel/Viber/ViberFile.php | 36 +++++ src/Messages/Channel/Viber/ViberImage.php | 12 +- .../Channel/Viber/ViberServiceObjectTrait.php | 50 ++++--- src/Messages/Channel/Viber/ViberText.php | 12 +- src/Messages/Channel/Viber/ViberVideo.php | 38 +++++ .../WhatsApp/MessageObjects/StickerObject.php | 69 +++++++++ .../Channel/WhatsApp/WhatsAppSticker.php | 41 ++++++ test/Messages/ClientTest.php | 132 ++++++++++++++++++ 10 files changed, 399 insertions(+), 30 deletions(-) create mode 100644 src/Messages/Channel/Viber/MessageObjects/ViberActionObject.php create mode 100644 src/Messages/Channel/Viber/ViberFile.php create mode 100644 src/Messages/Channel/Viber/ViberVideo.php create mode 100644 src/Messages/Channel/WhatsApp/MessageObjects/StickerObject.php create mode 100644 src/Messages/Channel/WhatsApp/WhatsAppSticker.php diff --git a/src/Messages/Channel/BaseMessage.php b/src/Messages/Channel/BaseMessage.php index 3a2868ac..d6be596d 100644 --- a/src/Messages/Channel/BaseMessage.php +++ b/src/Messages/Channel/BaseMessage.php @@ -17,6 +17,7 @@ abstract class BaseMessage implements Message public const MESSAGES_SUBTYPE_VIDEO = 'video'; public const MESSAGES_SUBTYPE_FILE = 'file'; public const MESSAGES_SUBTYPE_TEMPLATE = 'template'; + public const MESSAGES_SUBTYPE_STICKER = 'sticker'; public const MESSAGES_SUBTYPE_CUSTOM = 'custom'; public function getClientRef(): ?string diff --git a/src/Messages/Channel/Viber/MessageObjects/ViberActionObject.php b/src/Messages/Channel/Viber/MessageObjects/ViberActionObject.php new file mode 100644 index 00000000..a292d578 --- /dev/null +++ b/src/Messages/Channel/Viber/MessageObjects/ViberActionObject.php @@ -0,0 +1,38 @@ +url = $data['url']; + $this->text = $data['text']; + + return $this; + } + + public function toArray(): array + { + return [ + 'url' => $this->getUrl(), + 'text' => $this->getText() + ]; + } + + public function getUrl(): string + { + return $this->url; + } + + public function getText(): string + { + return $this->text; + } +} diff --git a/src/Messages/Channel/Viber/ViberFile.php b/src/Messages/Channel/Viber/ViberFile.php new file mode 100644 index 00000000..1f58dc9b --- /dev/null +++ b/src/Messages/Channel/Viber/ViberFile.php @@ -0,0 +1,36 @@ +to = $to; + $this->from = $from; + } + + public function toArray(): array + { + $returnArray = $this->getBaseMessageUniversalOutputArray(); + $returnArray['file'] = $this->fileObject->toArray(); + + if ($this->requiresViberServiceObject()) { + $this->getCategory() ? $returnArray['viber_service']['category'] = $this->getCategory(): null; + $this->getTtl() ? $returnArray['viber_service']['ttl'] = $this->getTtl(): null; + $this->getType() ? $returnArray['viber_service']['type'] = $this->getType(): null; + } + + return $returnArray; + } +} \ No newline at end of file diff --git a/src/Messages/Channel/Viber/ViberImage.php b/src/Messages/Channel/Viber/ViberImage.php index 982d91b6..aea4bcb4 100644 --- a/src/Messages/Channel/Viber/ViberImage.php +++ b/src/Messages/Channel/Viber/ViberImage.php @@ -2,6 +2,7 @@ namespace Vonage\Messages\Channel\Viber; +use Vonage\Messages\Channel\Viber\MessageObjects\ViberActionObject; use Vonage\Messages\MessageObjects\ImageObject; use Vonage\Messages\Channel\BaseMessage; @@ -18,13 +19,15 @@ public function __construct( protected ImageObject $image, ?string $category = null, ?int $ttl = null, - ?string $type = null + ?string $type = null, + ?ViberActionObject $viberActionObject = null ) { $this->to = $to; $this->from = $from; $this->category = $category; $this->ttl = $ttl; $this->type = $type; + $this->action = $viberActionObject; } public function toArray(): array @@ -33,9 +36,10 @@ public function toArray(): array $returnArray['image'] = $this->image->toArray(); if ($this->requiresViberServiceObject()) { - $returnArray['viber_service']['category'] = $this->getCategory(); - $returnArray['viber_service']['ttl'] = $this->getTtl(); - $returnArray['viber_service']['type'] = $this->getType(); + $this->getCategory() ? $returnArray['viber_service']['category'] = $this->getCategory(): null; + $this->getTtl() ? $returnArray['viber_service']['ttl'] = $this->getTtl(): null; + $this->getType() ? $returnArray['viber_service']['type'] = $this->getType(): null; + $this->getAction() ? $returnArray['viber_service']['action'] = $this->getAction()->toArray(): null; } return array_filter($returnArray); diff --git a/src/Messages/Channel/Viber/ViberServiceObjectTrait.php b/src/Messages/Channel/Viber/ViberServiceObjectTrait.php index e2600a91..89ad71ab 100644 --- a/src/Messages/Channel/Viber/ViberServiceObjectTrait.php +++ b/src/Messages/Channel/Viber/ViberServiceObjectTrait.php @@ -2,59 +2,65 @@ namespace Vonage\Messages\Channel\Viber; +use Vonage\Messages\Channel\Viber\MessageObjects\ViberActionObject; + trait ViberServiceObjectTrait { - private ?string $category; - private ?int $ttl; - private ?string $type; + private ?string $category = null; + private ?int $ttl = null; + private ?string $type = null; + private ?ViberActionObject $action = null; public function requiresViberServiceObject(): bool { - return $this->getCategory() || $this->getTtl() || $this->getType(); + return $this->getCategory() || $this->getTtl() || $this->getType() || $this->getAction(); } - /** - * @return string|null - */ public function getCategory(): ?string { return $this->category; } - public function setCategory(?string $category): void + public function setCategory(?string $category): static { $this->category = $category; + + return $this; } - /** - * @return int|null - */ public function getTtl(): ?int { return $this->ttl; } - /** - * @param int|null $ttl - */ - public function setTtl(int $ttl): void + public function setTtl(int $ttl): static { $this->ttl = $ttl; + + return $this; } - /** - * @return string|null - */ public function getType(): ?string { return $this->type; } - /** - * @param string|null $type - */ - public function setType(string $type): void + public function setType(string $type): static { $this->type = $type; + + return $this; + } + + public function getAction(): ?ViberActionObject + { + return $this->action; + } + + public function setAction(ViberActionObject $viberActionObject): static + { + $this->action = $viberActionObject; + + return $this; } } diff --git a/src/Messages/Channel/Viber/ViberText.php b/src/Messages/Channel/Viber/ViberText.php index 0807f8b0..8d9d860c 100644 --- a/src/Messages/Channel/Viber/ViberText.php +++ b/src/Messages/Channel/Viber/ViberText.php @@ -2,6 +2,7 @@ namespace Vonage\Messages\Channel\Viber; +use Vonage\Messages\Channel\Viber\MessageObjects\ViberActionObject; use Vonage\Messages\MessageTraits\TextTrait; use Vonage\Messages\Channel\BaseMessage; @@ -19,7 +20,8 @@ public function __construct( string $message, ?string $category = null, ?int $ttl = null, - ?string $type = null + ?string $type = null, + ?ViberActionObject $viberActionObject = null, ) { $this->to = $to; $this->from = $from; @@ -27,6 +29,7 @@ public function __construct( $this->category = $category; $this->ttl = $ttl; $this->type = $type; + $this->action = $viberActionObject; } public function toArray(): array @@ -35,9 +38,10 @@ public function toArray(): array $returnArray['text'] = $this->getText(); if ($this->requiresViberServiceObject()) { - $returnArray['viber_service']['category'] = $this->getCategory(); - $returnArray['viber_service']['ttl'] = $this->getTtl(); - $returnArray['viber_service']['type'] = $this->getType(); + $this->getCategory() ? $returnArray['viber_service']['category'] = $this->getCategory(): null; + $this->getTtl() ? $returnArray['viber_service']['ttl'] = $this->getTtl(): null; + $this->getType() ? $returnArray['viber_service']['type'] = $this->getType(): null; + $this->getAction() ? $returnArray['viber_service']['action'] = $this->getAction()->toArray(): null; } return array_filter($returnArray); diff --git a/src/Messages/Channel/Viber/ViberVideo.php b/src/Messages/Channel/Viber/ViberVideo.php new file mode 100644 index 00000000..9588db2a --- /dev/null +++ b/src/Messages/Channel/Viber/ViberVideo.php @@ -0,0 +1,38 @@ +to = $to; + $this->from = $from; + $this->thumbUrl = $thumbUrl; + } + + public function toArray(): array + { + $returnArray = $this->getBaseMessageUniversalOutputArray(); + $videoArray = $this->videoObject->toArray(); + $videoArray['thumb_url'] = $this->thumbUrl; + $returnArray['video'] = $videoArray; + + return $returnArray; + } +} diff --git a/src/Messages/Channel/WhatsApp/MessageObjects/StickerObject.php b/src/Messages/Channel/WhatsApp/MessageObjects/StickerObject.php new file mode 100644 index 00000000..4cb1e118 --- /dev/null +++ b/src/Messages/Channel/WhatsApp/MessageObjects/StickerObject.php @@ -0,0 +1,69 @@ +allowedTypes, true)) { + throw new \InvalidArgumentException($type . ' is an invalid type of Sticker'); + } + } + + public function fromArray(array $data): StickerObject + { + if (! in_array($data['type'], $this->allowedTypes, true)) { + throw new \InvalidArgumentException($data['type'] . ' is an invalid type of Sticker'); + } + + return $this; + } + + /** + * @return string + */ + public function getType(): string + { + return $this->type; + } + + /** + * @param string $type + */ + public function setType(string $type): void + { + $this->type = $type; + } + + /** + * @return string + */ + public function getValue(): string + { + return $this->value; + } + + /** + * @param string $value + */ + public function setValue(string $value): void + { + $this->value = $value; + } + + public function toArray(): array + { + return [$this->getType() => $this->getValue()]; + } +} diff --git a/src/Messages/Channel/WhatsApp/WhatsAppSticker.php b/src/Messages/Channel/WhatsApp/WhatsAppSticker.php new file mode 100644 index 00000000..cefaec5f --- /dev/null +++ b/src/Messages/Channel/WhatsApp/WhatsAppSticker.php @@ -0,0 +1,41 @@ +to = $to; + $this->from = $from; + } + + public function getSticker(): StickerObject + { + return $this->sticker; + } + + public function setSticker(StickerObject $sticker): static + { + $this->sticker = $sticker; + + return $this; + } + + public function toArray(): array + { + $returnArray = $this->getBaseMessageUniversalOutputArray(); + $returnArray['sticker'] = $this->getSticker()->toArray(); + + return $returnArray; + } +} diff --git a/test/Messages/ClientTest.php b/test/Messages/ClientTest.php index fd626347..e900903e 100644 --- a/test/Messages/ClientTest.php +++ b/test/Messages/ClientTest.php @@ -16,6 +16,12 @@ use Prophecy\Argument; use Prophecy\Prophecy\ObjectProphecy; use Vonage\Client\APIResource; +use Vonage\Messages\Channel\BaseMessage; +use Vonage\Messages\Channel\Viber\MessageObjects\ViberActionObject; +use Vonage\Messages\Channel\Viber\ViberFile; +use Vonage\Messages\Channel\Viber\ViberVideo; +use Vonage\Messages\Channel\WhatsApp\MessageObjects\StickerObject; +use Vonage\Messages\Channel\WhatsApp\WhatsAppSticker; use Vonage\Messages\ExceptionErrorHandler; use Vonage\Messages\MessageObjects\AudioObject; use Vonage\Messages\MessageObjects\FileObject; @@ -405,6 +411,43 @@ public function testCanSendWhatsAppTemplate(): void $this->assertArrayHasKey('message_uuid', $result); } + /** + * @dataProvider stickerTypeProvider + */ + public function testCanSendWhatsAppSticker($type, $value, $valid): void + { + if (!$valid) { + $this->expectException(\InvalidArgumentException::class); + } + + $stickerObject = new StickerObject( + $type, + $value + ); + + $payload = [ + 'to' => '447700900000', + 'from' => '16105551212', + 'sticker' => $stickerObject + ]; + + $message = new WhatsAppSticker($payload['to'], $payload['from'], $stickerObject); + + $this->vonageClient->send(Argument::that(function (Request $request) use ($payload, $type) { + $this->assertRequestJsonBodyContains('to', $payload['to'], $request); + $this->assertRequestJsonBodyContains('from', $payload['from'], $request); + $this->assertRequestJsonBodyContains('channel', 'whatsapp', $request); + $this->assertRequestJsonBodyContains('message_type', BaseMessage::MESSAGES_SUBTYPE_STICKER, $request); + $this->assertEquals('POST', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('sms-success', 202)); + + $result = $this->messageClient->send($message); + $this->assertIsArray($result); + $this->assertArrayHasKey('message_uuid', $result); + } + public function testCanSendWhatsAppCustom(): void { $payload = [ @@ -637,6 +680,7 @@ public function testCanSendViberText(): void return true; }))->willReturn($this->getResponse('sms-success', 202)); + $result = $this->messageClient->send($message); $this->assertIsArray($result); $this->assertArrayHasKey('message_uuid', $result); @@ -719,6 +763,7 @@ public function testCanSendViberTextWithoutViberObject(): void return true; }))->willReturn($this->getResponse('sms-success', 202)); + $result = $this->messageClient->send($message); $this->assertIsArray($result); $this->assertArrayHasKey('message_uuid', $result); @@ -758,6 +803,84 @@ public function testCanSendViberImage(): void return true; }))->willReturn($this->getResponse('sms-success', 202)); + + $result = $this->messageClient->send($message); + $this->assertIsArray($result); + $this->assertArrayHasKey('message_uuid', $result); + } + + public function testCanSendViberFile(): void + { + $fileObject = new FileObject( + 'https://file-examples.com/wp-content/uploads/2017/04/file_example_MP4_480_1_5MG.mp4', + 'some file' + ); + + $payload = [ + 'to' => '447700900000', + 'from' => '16105551212', + 'file' => $fileObject + ]; + + $message = new ViberFile( + $payload['to'], + $payload['from'], + $payload['file'] + ); + + $this->vonageClient->send(Argument::that(function (Request $request) use ($payload) { + $this->assertRequestJsonBodyContains('to', $payload['to'], $request); + $this->assertRequestJsonBodyContains('from', $payload['from'], $request); + $this->assertRequestJsonBodyContains('file', $payload['file']->toArray(), $request); + $this->assertRequestJsonBodyContains('channel', 'viber_service', $request); + $this->assertRequestJsonBodyContains('message_type', 'file', $request); + + $this->assertEquals('POST', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('sms-success', 202)); + + $result = $this->messageClient->send($message); + $this->assertIsArray($result); + $this->assertArrayHasKey('message_uuid', $result); + } + + public function testCanSendViberVideo(): void + { + $videoObject = new VideoObject( + 'https://file-examples.com/wp-content/uploads/2017/04/file_example_MP4_480_1_5MG.mp4', + 'some video' + ); + + $payload = [ + 'to' => '447700900000', + 'from' => '16105551212', + 'video' => $videoObject, + 'thumb' => 'https://file-examples.com/wp-content/uploads/2017/04/preview.jpg' + ]; + + $message = new ViberVideo( + $payload['to'], + $payload['from'], + $payload['thumb'], + $payload['video'] + ); + + $videoMatch = $videoObject->toArray(); + $videoMatch['thumb_url'] = $payload['thumb']; + + $this->vonageClient->send(Argument::that(function (Request $request) use ($payload, $videoMatch) { + $this->assertRequestJsonBodyContains('to', $payload['to'], $request); + $this->assertRequestJsonBodyContains('from', $payload['from'], $request); + $this->assertRequestJsonBodyContains('video', $videoMatch, $request); + $this->assertRequestJsonBodyContains('channel', 'viber_service', $request); + $this->assertRequestJsonBodyContains('message_type', 'video', $request); + + $this->assertEquals('POST', $request->getMethod()); + + return true; + }))->willReturn($this->getResponse('sms-success', 202)); + $result = $this->messageClient->send($message); $this->assertIsArray($result); $this->assertArrayHasKey('message_uuid', $result); @@ -770,4 +893,13 @@ protected function getResponse(string $identifier, int $status = 200): Response { return new Response(fopen(__DIR__ . '/Fixtures/Responses/' . $identifier . '.json', 'rb'), $status); } + + public function stickerTypeProvider(): array + { + return [ + ['url', 'https://example.com', true], + ['id', 'ds87g8-ds9g8s098-asdhj8-dsifug8', true], + ['caption', 'this is not valid', false] + ]; + } }