Skip to content

Commit 22694f7

Browse files
authored
Feature/conversations (#478)
* WIP * WIP * WIP * WIP * WIP * refactor to remove attempt at putting all event objects in * Added docs * phpstan fix number object
1 parent db2cdad commit 22694f7

39 files changed

+3309
-6
lines changed

README.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,116 @@ If you would like to have the system randomly pick a FROM number from the number
445445
leave off the second parameter to `\Vonage\Voice\OutboundCall`'s constructor, and the system will select a number
446446
at random for you.
447447

448+
## Using the Conversations API
449+
450+
This API is used for in-app messaging and is contains a wide range of features and
451+
concepts. For more information, take a look at the [API Documentation]()
452+
453+
### Retrieve a list of Conversations with Filter
454+
455+
```php
456+
$credentials = new \Vonage\Client\Credentials\Keypair(file_get_contents('./path-to-my-key.key', 'my-app-id'));
457+
$client = new \Vonage\Client($credentials);
458+
$filter = new \Vonage\Conversation\Filter\ListConversationFilter();
459+
$filter->setStartDate('2018-01-01 10:00:00');
460+
$filter->setEndDate('2019-01-01 10:00:00')
461+
462+
$conversations = $client->conversations()->listConversations($filter)
463+
464+
var_dump($conversations);
465+
```
466+
467+
### Create a Conversation
468+
469+
```php
470+
471+
$credentials = new \Vonage\Client\Credentials\Keypair(file_get_contents('./path-to-my-key.key', 'my-app-id'));
472+
$client = new \Vonage\Client($credentials);
473+
474+
$conversation = new CreateConversationRequest('customer_chat', 'Customer Chat', 'https://example.com/image.png');
475+
$conversation->setTtl(60);
476+
477+
$conversationNumber = new ConversationNumber('447700900000');
478+
479+
$conversationCallback = new ConversationCallback('https://example.com/eventcallback');
480+
$conversationCallback->setEventMask('member:invited, member:joined');
481+
$conversationCallback->setApplicationId('afa393df-2c46-475b-b2d6-92da4ea05481');
482+
$conversationCallback->setNccoUrl('https://example.com/ncco');
483+
484+
$conversation->setNumber($conversationNumber);
485+
$conversation->setConversationCallback($conversationCallback);
486+
487+
$response = $this->conversationsClient->createConversation($conversation);
488+
489+
var_dump($response);
490+
491+
```
492+
493+
### List Members in a Conversation
494+
495+
```php
496+
497+
$credentials = new \Vonage\Client\Credentials\Keypair(file_get_contents('./path-to-my-key.key', 'my-app-id'));
498+
$client = new \Vonage\Client($credentials);
499+
500+
$filter = new ListUserConversationsFilter();
501+
$filter->setState('INVITED');
502+
$filter->setIncludeCustomData(true);
503+
$filter->setOrderBy('created');
504+
$filter->setStartDate('2018-01-01 10:00:00');
505+
$filter->setEndDate('2018-01-01 12:00:00');
506+
$filter->setPageSize(5);
507+
$filter->setOrder('asc');
508+
509+
$response = $this->conversationsClient->listUserConversationsByUserId('CON-d66d47de-5bcb-4300-94f0-0c9d4b948e9a');
510+
511+
foreach ($response as $member) {
512+
$members[] = $member;
513+
}
514+
515+
var_dump($members);
516+
517+
```
518+
519+
### Create a Member in a Conversation
520+
521+
```php
522+
523+
$channel = Channel::createChannel(Channel::CHANNEL_TYPE_APP);
524+
$channel->addUserFromTypes([
525+
'sms',
526+
'phone'
527+
]);
528+
529+
$channel->addUserToField('USR-82e028d9-9999-4f1e-8188-604b2d3471ec');
530+
531+
$createMemberRequest = new CreateMemberRequest(
532+
'invited',
533+
$channel,
534+
'USR-82e028d9-5201-4f1e-8188-604b2d3471ec',
535+
'my_user_name',
536+
);
537+
538+
$createMemberRequest->setAudioPossible(true);
539+
$createMemberRequest->setAudioEnabled(true);
540+
$createMemberRequest->setAudioEarmuffed(false);
541+
$createMemberRequest->setAudioMuted(false);
542+
$createMemberRequest->setKnockingId('4f1e-8188');
543+
$createMemberRequest->setMemberIdInviting('MEM-63f61863-4a51-4f6b-86e1-46edebio0391');
544+
$createMemberRequest->setFrom('value');
545+
546+
$response = $this->conversationsClient->createMember(
547+
$createMemberRequest,
548+
'CON-63f61863-4a51-4f6b-86e1-46edebio0391'
549+
);
550+
551+
var_dump($response);
552+
````
553+
448554
### Building a call with NCCO Actions
449555

556+
### Create an Event
557+
450558
Full parameter lists for NCCO Actions can be found in the [Voice API Docs](https://developer.nexmo.com/voice/voice-api/ncco-reference).
451559

452560
Each of these examples uses the following structure to add actions to a call:

phpunit.xml.dist

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
<testsuite name="verify2">
2424
<directory>test/Verify2</directory>
2525
</testsuite>
26+
<testsuite name="conversations">
27+
<directory>test/Conversation</directory>
28+
</testsuite>
2629
<testsuite name="proactive_connect">
2730
<directory>test/ProactiveConnect</directory>
2831
</testsuite>

src/Client.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
use Vonage\Users\ClientFactory as UsersClientFactory;
5050
use Vonage\Verify\ClientFactory as VerifyClientFactory;
5151
use Vonage\Verify2\ClientFactory as Verify2ClientFactory;
52+
use Vonage\Conversation\ClientFactory as ConversationClientFactory;
5253
use Vonage\Verify\Verification;
5354
use Vonage\Voice\ClientFactory as VoiceClientFactory;
5455
use Vonage\Logger\{LoggerAwareInterface, LoggerTrait};
@@ -73,6 +74,7 @@
7374
* @method Messages\Client messages()
7475
* @method Application\Client applications()
7576
* @method Conversion\Client conversion()
77+
* @method Conversation\Client conversations()
7678
* @method Insights\Client insights()
7779
* @method Numbers\Client numbers()
7880
* @method Redact\Client redact()
@@ -210,6 +212,7 @@ public function __construct(
210212
'account' => ClientFactory::class,
211213
'applications' => ApplicationClientFactory::class,
212214
'conversion' => ConversionClientFactory::class,
215+
'conversation' => ConversationClientFactory::class,
213216
'insights' => InsightsClientFactory::class,
214217
'numbers' => NumbersClientFactory::class,
215218
'meetings' => MeetingsClientFactory::class,

src/Conversation/Client.php

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
<?php
2+
3+
namespace Vonage\Conversation;
4+
5+
use Vonage\Client\APIClient;
6+
use Vonage\Client\APIResource;
7+
use Vonage\Conversation\ConversationObjects\EventRequest;
8+
use Vonage\Conversation\ConversationObjects\Conversation;
9+
use Vonage\Conversation\ConversationObjects\CreateConversationRequest;
10+
use Vonage\Conversation\ConversationObjects\CreateMemberRequest;
11+
use Vonage\Conversation\ConversationObjects\Event;
12+
use Vonage\Conversation\ConversationObjects\Member;
13+
use Vonage\Conversation\ConversationObjects\UpdateConversationRequest;
14+
use Vonage\Conversation\ConversationObjects\UpdateMemberRequest;
15+
use Vonage\Conversation\Filter\ListConversationFilter;
16+
use Vonage\Conversation\Filter\ListEventsFilter;
17+
use Vonage\Conversation\Filter\ListMembersFilter;
18+
use Vonage\Conversation\Filter\ListUserConversationsFilter;
19+
use Vonage\Entity\Hydrator\ArrayHydrator;
20+
use Vonage\Entity\IterableAPICollection;
21+
22+
class Client implements APIClient
23+
{
24+
public function __construct(protected APIResource $api)
25+
{
26+
}
27+
28+
public function getAPIResource(): APIResource
29+
{
30+
return $this->api;
31+
}
32+
33+
public function listConversations(ListConversationFilter $conversationFilter = null): IterableAPICollection
34+
{
35+
if (!$conversationFilter) {
36+
$conversationFilter = new ListConversationFilter();
37+
}
38+
39+
$response = $this->getApiResource()->search($conversationFilter);
40+
$response->setHasPagination(false);
41+
$response->setNaiveCount(true);
42+
43+
$hydrator = new ArrayHydrator();
44+
$hydrator->setPrototype(new Conversation());
45+
$response->setHydrator($hydrator);
46+
47+
return $response;
48+
}
49+
50+
public function createConversation(CreateConversationRequest $createConversation): Conversation
51+
{
52+
$response = $this->getApiResource()->create($createConversation->toArray());
53+
$conversation = new Conversation();
54+
$conversation->fromArray($response);
55+
56+
return $conversation;
57+
}
58+
59+
public function getConversationById(string $id): Conversation
60+
{
61+
$response = $this->getApiResource()->get($id);
62+
$conversation = new Conversation();
63+
$conversation->fromArray($response);
64+
65+
return $conversation;
66+
}
67+
68+
public function updateConversationById(string $id, UpdateConversationRequest $updateRequest): Conversation
69+
{
70+
$response = $this->getApiResource()->update($id, $updateRequest->toArray());
71+
$conversation = new Conversation();
72+
$conversation->fromArray($response);
73+
74+
return $conversation;
75+
}
76+
77+
public function deleteConversationById(string $id): bool
78+
{
79+
$this->getApiResource()->delete($id);
80+
81+
return true;
82+
}
83+
84+
public function listUserConversationsByUserId(
85+
string $userId,
86+
?ListUserConversationsFilter $filter = null
87+
): IterableAPICollection {
88+
$api = clone $this->getAPIResource();
89+
$api->setBaseUrl('https://api.nexmo.com/v1/users');
90+
$response = $api->search($filter, '/' . $userId . '/conversations');
91+
$response->setHasPagination(true);
92+
$response->setNaiveCount(true);
93+
94+
$hydrator = new ArrayHydrator();
95+
$hydrator->setPrototype(new Conversation());
96+
$response->setHydrator($hydrator);
97+
98+
return $response;
99+
}
100+
101+
public function listMembersByConversationId(
102+
string $conversationId,
103+
?ListMembersFilter $filter = null
104+
): IterableAPICollection {
105+
$api = clone $this->getAPIResource();
106+
$api->setBaseUrl('https://api.nexmo.com/v1/users');
107+
$api->setCollectionName('members');
108+
$response = $api->search($filter, $conversationId . '/members');
109+
$response->setHasPagination(true);
110+
$response->setNaiveCount(true);
111+
112+
$hydrator = new ArrayHydrator();
113+
$hydrator->setPrototype(new Member());
114+
$response->setHydrator($hydrator);
115+
116+
return $response;
117+
}
118+
119+
public function createMember(CreateMemberRequest $createMemberRequest, string $conversationId): ?array
120+
{
121+
return $this->getApiResource()->create($createMemberRequest->toArray(), '/' . $conversationId . '/members');
122+
}
123+
124+
public function getMyMemberByConversationId(string $id): Member
125+
{
126+
$response = $this->getApiResource()->get($id . '/members/me');
127+
$member = new Member();
128+
$member->fromArray($response);
129+
130+
return $member;
131+
}
132+
133+
public function getMemberByConversationId(string $memberId, string $conversationId): Member
134+
{
135+
$response = $this->getApiResource()->get($conversationId . '/members/' . $memberId);
136+
$member = new Member();
137+
$member->fromArray($response);
138+
139+
return $member;
140+
}
141+
142+
public function updateMember(UpdateMemberRequest $updateMemberRequest): Member
143+
{
144+
$response = $this->getAPIResource()->update(
145+
$updateMemberRequest->getConversationId() . '/members/' . $updateMemberRequest->getMemberId(),
146+
$updateMemberRequest->toArray()
147+
);
148+
149+
$member = new Member();
150+
$member->fromArray($response);
151+
152+
return $member;
153+
}
154+
155+
public function createEvent(EventRequest $event): Event
156+
{
157+
$response = $this->getAPIResource()->create($event->toArray(), '/' . $event->getConversationId() . '/events');
158+
159+
$member = new Event();
160+
$member->fromArray($response);
161+
162+
return $member;
163+
}
164+
165+
public function listEvents(string $conversationId, ListEventsFilter $filter): IterableAPICollection
166+
{
167+
$response = $this->getAPIResource()->search($filter, '/' . $conversationId . '/events');
168+
$response->setHasPagination(false);
169+
$response->setNaiveCount(true);
170+
$response->setHalNoCollection(true);
171+
172+
return $response;
173+
}
174+
175+
public function getEventById(string $eventId, string $conversationId): Event
176+
{
177+
$response = $this->getApiResource()->get($conversationId . '/events/' . $eventId);
178+
$member = new Event();
179+
$member->fromArray($response);
180+
181+
return $member;
182+
}
183+
184+
public function deleteEventById(string $eventId, $conversationId): bool
185+
{
186+
$this->getApiResource()->delete($conversationId . '/events/' . $eventId);
187+
188+
return true;
189+
}
190+
}

src/Conversation/ClientFactory.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<?php
2+
3+
namespace Vonage\Conversation;
4+
5+
use Psr\Container\ContainerInterface;
6+
use Vonage\Client\APIResource;
7+
use Vonage\Client\Credentials\Handler\KeypairHandler;
8+
use Vonage\Verify2\Client;
9+
10+
class ClientFactory
11+
{
12+
public function __invoke(ContainerInterface $container): Client
13+
{
14+
$api = $container->make(APIResource::class);
15+
$api->setIsHAL(true)
16+
->setErrorsOn200(false)
17+
->setAuthHandler(new KeypairHandler())
18+
->setBaseUrl('https://api.nexmo.com/v1/conversations');
19+
20+
return new Client($api);
21+
}
22+
}

0 commit comments

Comments
 (0)