Skip to content

Commit 4d9540e

Browse files
authored
Fixes NCCO parsing to and from arrays (#495)
* update stream factory to accept arrays and strings * Add tests, fix NCCO action factories casting incorrect data types --------- Co-authored-by: Sam Taylor <15961687+samueljtaylor@users.noreply.github.com>
1 parent 700cd53 commit 4d9540e

File tree

6 files changed

+306
-4
lines changed

6 files changed

+306
-4
lines changed

src/Voice/NCCO/Action/Input.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,9 @@ public static function factory(array $data): Input
8484
if (array_key_exists('dtmf', $data)) {
8585
$dtmf = $data['dtmf'];
8686
$action->setEnableDtmf(true);
87+
if (is_object($dtmf)) {
88+
$dtmf = (array)$dtmf;
89+
}
8790

8891
if (array_key_exists('timeOut', $dtmf)) {
8992
$action->setDtmfTimeout((int)$dtmf['timeOut']);
@@ -103,6 +106,9 @@ public static function factory(array $data): Input
103106
if (array_key_exists('speech', $data)) {
104107
$speech = $data['speech'];
105108
$action->setEnableSpeech(true);
109+
if (is_object($speech)) {
110+
$speech = (array)$speech;
111+
}
106112

107113
if (array_key_exists('uuid', $speech)) {
108114
$action->setSpeechUUID($speech['uuid'][0]);

src/Voice/NCCO/Action/Notify.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ public function __construct(protected array $payload, protected ?\Vonage\Voice\W
2121
public static function factory(array $payload, array $data): Notify
2222
{
2323
if (array_key_exists('eventUrl', $data)) {
24+
if (is_array($data['eventUrl'])) {
25+
$data['eventUrl'] = $data['eventUrl'][0];
26+
}
2427
if (array_key_exists('eventMethod', $data)) {
2528
$webhook = new Webhook($data['eventUrl'], $data['eventMethod']);
2629
} else {

src/Voice/NCCO/Action/Record.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,9 @@ public static function factory(array $data): self
7171
}
7272

7373
if (array_key_exists('channels', $data)) {
74-
$action->setChannels($data['channels']);
74+
$action->setChannels(
75+
filter_var($data['channels'], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE)
76+
);
7577
}
7678

7779
if (array_key_exists('endOnSilence', $data)) {
@@ -85,7 +87,9 @@ public static function factory(array $data): self
8587
}
8688

8789
if (array_key_exists('timeOut', $data)) {
88-
$action->setTimeout($data['timeOut']);
90+
$action->setTimeout(
91+
filter_var($data['timeOut'], FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE)
92+
);
8993
}
9094

9195
if (array_key_exists('beepStart', $data)) {
@@ -95,6 +99,9 @@ public static function factory(array $data): self
9599
}
96100

97101
if (array_key_exists('eventUrl', $data)) {
102+
if (is_array($data['eventUrl'])) {
103+
$data['eventUrl'] = $data['eventUrl'][0];
104+
}
98105
if (array_key_exists('eventMethod', $data)) {
99106
$webhook = new Webhook($data['eventUrl'], $data['eventMethod']);
100107
} else {

src/Voice/NCCO/Action/Stream.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,13 @@ public function __construct(protected string $streamUrl)
3030
}
3131

3232
/**
33-
* @param array{streamUrl: string, bargeIn?: bool, level?: float, loop?: int, voiceName?: string} $data
33+
* @param array{streamUrl: string|array, bargeIn?: bool, level?: float, loop?: int, voiceName?: string} $data
3434
*/
35-
public static function factory(string $streamUrl, array $data): Stream
35+
public static function factory(string|array $streamUrl, array $data): Stream
3636
{
37+
if (is_array($streamUrl)) {
38+
$streamUrl = $streamUrl[0];
39+
}
3740
$stream = new Stream($streamUrl);
3841

3942
if (array_key_exists('bargeIn', $data)) {

test/Voice/NCCO/Action/StreamTest.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,20 @@ public function testJsonSerializeLooksCorrect(): void
3131
->setLoop(1)
3232
->jsonSerialize());
3333
}
34+
35+
public function testFactoryWithArray(): void
36+
{
37+
$this->assertSame([
38+
'action' => 'stream',
39+
'streamUrl' => ['https://test.domain/music.mp3']
40+
], Stream::factory(['https://test.domain/music.mp3'], [])->toNCCOArray());
41+
}
42+
43+
public function testFactoryWithString(): void
44+
{
45+
$this->assertSame([
46+
'action' => 'stream',
47+
'streamUrl' => ['https://test.domain/music.mp3']
48+
], Stream::factory('https://test.domain/music.mp3', [])->toNCCOArray());
49+
}
3450
}

test/Voice/NCCO/NCCOTest.php

Lines changed: 267 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,271 @@ public function testCanCreateNCCOFromArray(): void
8989
$this->assertCount(7, $json);
9090
$this->assertEquals($data[0], $json[0]);
9191
}
92+
93+
public function testCanCreateFromValidNCCOArray(): void
94+
{
95+
$data = [
96+
[
97+
"action" => "talk",
98+
"text" => "Thank you for trying Vonage",
99+
"bargeIn" => "false",
100+
"level" => "0",
101+
"loop" => "1",
102+
"language" => "en-US",
103+
"style" => "0",
104+
"premium" => "false",
105+
],
106+
[
107+
"action" => "record",
108+
"format" => "wav",
109+
"beepStart" => "true",
110+
"endOnSilence" => "4",
111+
"endOnKey" => "#",
112+
"channels" => "12",
113+
"split" => "conversation",
114+
"timeOut" => "7200",
115+
"eventUrl" => [
116+
"http://domain.test/event",
117+
],
118+
"eventMethod" => "POST",
119+
],
120+
[
121+
"action" => "conversation",
122+
"name" => "Sample Conversation",
123+
"startOnEnter" => "true",
124+
"endOnExit" => "false",
125+
"record" => "true",
126+
"canSpeak" => [
127+
"49502bca-da71-44bb-b3a6-5077b58c2690",
128+
],
129+
"canHear" => [
130+
"798146f0-af79-468a-83a4-b6fcda7cd4e6",
131+
],
132+
],
133+
[
134+
"action" => "connect",
135+
"endpoint" => [
136+
[
137+
"type" => "phone",
138+
"number" => "447700900001",
139+
],
140+
],
141+
],
142+
[
143+
"action" => "talk",
144+
"text" => "Thank you for trying Vonage",
145+
"bargeIn" => "false",
146+
"level" => "0",
147+
"loop" => "1",
148+
"language" => "en-US",
149+
"style" => "0",
150+
"premium" => "false",
151+
],
152+
[
153+
"action" => "record",
154+
"format" => "wav",
155+
"beepStart" => "true",
156+
"endOnSilence" => "4",
157+
"endOnKey" => "#",
158+
"channels" => "12",
159+
"split" => "conversation",
160+
"timeOut" => "7200",
161+
"eventUrl" => [
162+
"http://domain.test/event",
163+
],
164+
"eventMethod" => "POST",
165+
],
166+
[
167+
"action" => "conversation",
168+
"name" => "Sample Conversation",
169+
"startOnEnter" => "true",
170+
"endOnExit" => "false",
171+
"record" => "true",
172+
"canSpeak" => [
173+
"49502bca-da71-44bb-b3a6-5077b58c2690",
174+
],
175+
"canHear" => [
176+
"798146f0-af79-468a-83a4-b6fcda7cd4e6",
177+
],
178+
],
179+
[
180+
"action" => "connect",
181+
"endpoint" => [
182+
[
183+
"type" => "phone",
184+
"number" => "447700900001",
185+
],
186+
],
187+
],
188+
[
189+
"action" => "stream",
190+
"streamUrl" => [
191+
"http://domain.test/music.mp3",
192+
],
193+
"bargeIn" => "true",
194+
"level" => "0.1",
195+
"loop" => "0",
196+
],
197+
[
198+
"action" => "input",
199+
"dtmf" => [
200+
"maxDigits" => 1,
201+
],
202+
"speech" => [
203+
"uuid" => [
204+
"49502bca-da71-44bb-b3a6-5077b58c2690",
205+
],
206+
"maxDuration" => 30,
207+
],
208+
],
209+
[
210+
"action" => "notify",
211+
"payload" => [
212+
"foo" => "bar",
213+
],
214+
"eventUrl" => [
215+
"http://domain.test/event",
216+
],
217+
"eventMethod" => "POST",
218+
],
219+
];
220+
$ncco = new NCCO();
221+
$ncco->fromArray($data);
222+
$this->assertEquals(json_encode($data), json_encode($ncco));
223+
}
224+
225+
public function testCanConvertToAndFromArray(): void
226+
{
227+
$data = [
228+
[
229+
"action" => "talk",
230+
"text" => "Thank you for trying Vonage",
231+
"bargeIn" => "false",
232+
"level" => "0",
233+
"loop" => "1",
234+
"language" => "en-US",
235+
"style" => "0",
236+
"premium" => "false",
237+
],
238+
[
239+
"action" => "record",
240+
"format" => "wav",
241+
"beepStart" => "true",
242+
"endOnSilence" => "4",
243+
"endOnKey" => "#",
244+
"channels" => "12",
245+
"split" => "conversation",
246+
"timeOut" => "7200",
247+
"eventUrl" => [
248+
"http://domain.test/event",
249+
],
250+
"eventMethod" => "POST",
251+
],
252+
[
253+
"action" => "conversation",
254+
"name" => "Sample Conversation",
255+
"startOnEnter" => "true",
256+
"endOnExit" => "false",
257+
"record" => "true",
258+
"canSpeak" => [
259+
"49502bca-da71-44bb-b3a6-5077b58c2690",
260+
],
261+
"canHear" => [
262+
"798146f0-af79-468a-83a4-b6fcda7cd4e6",
263+
],
264+
],
265+
[
266+
"action" => "connect",
267+
"endpoint" => [
268+
[
269+
"type" => "phone",
270+
"number" => "447700900001",
271+
],
272+
],
273+
],
274+
[
275+
"action" => "talk",
276+
"text" => "Thank you for trying Vonage",
277+
"bargeIn" => "false",
278+
"level" => "0",
279+
"loop" => "1",
280+
"language" => "en-US",
281+
"style" => "0",
282+
"premium" => "false",
283+
],
284+
[
285+
"action" => "record",
286+
"format" => "wav",
287+
"beepStart" => "true",
288+
"endOnSilence" => "4",
289+
"endOnKey" => "#",
290+
"channels" => "12",
291+
"split" => "conversation",
292+
"timeOut" => "7200",
293+
"eventUrl" => [
294+
"http://domain.test/event",
295+
],
296+
"eventMethod" => "POST",
297+
],
298+
[
299+
"action" => "conversation",
300+
"name" => "Sample Conversation",
301+
"startOnEnter" => "true",
302+
"endOnExit" => "false",
303+
"record" => "true",
304+
"canSpeak" => [
305+
"49502bca-da71-44bb-b3a6-5077b58c2690",
306+
],
307+
"canHear" => [
308+
"798146f0-af79-468a-83a4-b6fcda7cd4e6",
309+
],
310+
],
311+
[
312+
"action" => "connect",
313+
"endpoint" => [
314+
[
315+
"type" => "phone",
316+
"number" => "447700900001",
317+
],
318+
],
319+
],
320+
[
321+
"action" => "stream",
322+
"streamUrl" => [
323+
"http://domain.test/music.mp3",
324+
],
325+
"bargeIn" => "true",
326+
"level" => "0.1",
327+
"loop" => "0",
328+
],
329+
[
330+
"action" => "input",
331+
"dtmf" => [
332+
"maxDigits" => 1,
333+
],
334+
"speech" => [
335+
"uuid" => [
336+
"49502bca-da71-44bb-b3a6-5077b58c2690",
337+
],
338+
"maxDuration" => 30,
339+
],
340+
],
341+
[
342+
"action" => "notify",
343+
"payload" => [
344+
"foo" => "bar",
345+
],
346+
"eventUrl" => [
347+
"http://domain.test/event",
348+
],
349+
"eventMethod" => "POST",
350+
],
351+
];
352+
$ncco1 = new NCCO();
353+
$ncco2 = new NCCO();
354+
$ncco1->fromArray($data);
355+
$ncco2->fromArray($ncco1->toArray());
356+
$this->assertEquals($ncco1->toArray(), $ncco2->toArray());
357+
$this->assertEquals(json_encode($data), json_encode($ncco2));
358+
}
92359
}

0 commit comments

Comments
 (0)