Skip to content

Commit e1be46f

Browse files
committed
Merge pull request #10 from clue/values
Support handling fields with multiple values and unify its handling
2 parents 4c78061 + 19e4709 commit e1be46f

9 files changed

Lines changed: 164 additions & 23 deletions

File tree

example/commands.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434

3535
$api->command($line)->then(
3636
function (Response $response) {
37-
echo $response->getField('_') . PHP_EOL;
37+
echo $response->getFieldValue('_') . PHP_EOL;
3838
},
3939
function (Exception $error) use ($line) {
4040
echo 'Error executing "' . $line . '": ' . $error->getMessage() . PHP_EOL;

src/Client.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ public function handleMessage(Message $message)
7979
return;
8080
}
8181

82-
if ($message->getField('Response') === 'Error') {
82+
if ($message->getFieldValue('Response') === 'Error') {
8383
$this->pending[$id]->reject(new ErrorException($message));
8484
} else {
8585
$this->pending[$id]->resolve($message);

src/Protocol/Action.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,22 @@ class Action extends Message
66
{
77
public function __construct(array $fields = array())
88
{
9+
foreach ($fields as $key => &$value) {
10+
if (is_array($value)) {
11+
foreach ($value as $k => &$v) {
12+
if ($v === null) {
13+
unset($value[$k]);
14+
} elseif (!is_int($k)) {
15+
$v = $k . '=' . $v;
16+
}
17+
}
18+
$value = array_values($value);
19+
}
20+
21+
if ($value === null || $value === array()) {
22+
unset($fields[$key]);
23+
}
24+
}
925
$this->fields = $fields;
1026
}
1127

@@ -17,9 +33,6 @@ public function getMessageSerialized()
1733
$values = array($values);
1834
}
1935
foreach ($values as $i => $value) {
20-
if (!is_int($i)) {
21-
$value = $i . '=' . $value;
22-
}
2336
$message .= $key . ': ' . $value . "\r\n";
2437
}
2538
}

src/Protocol/ErrorException.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class ErrorException extends RuntimeException
1010

1111
public function __construct(Response $response)
1212
{
13-
parent::__construct('Error "' . $response->getField('Message') . '"');
13+
parent::__construct('Error "' . $response->getFieldValue('Message') . '"');
1414
$this->response = $response;
1515
}
1616

src/Protocol/Event.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ public function __construct(array $fields)
1111

1212
public function getName()
1313
{
14-
return $this->getField('Event');
14+
return $this->getFieldValue('Event');
1515
}
1616
}

src/Protocol/Message.php

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,77 @@ abstract class Message
88

99
public function getActionId()
1010
{
11-
return $this->getField('ActionId');
11+
return $this->getFieldValue('ActionId');
1212
}
1313

14-
public function getField($key)
14+
/**
15+
* Returns the first value for the field with the given $key
16+
*
17+
* @param string $key
18+
* @return string|NULL
19+
*/
20+
public function getFieldValue($key)
1521
{
1622
$key = strtolower($key);
1723

1824
foreach ($this->fields as $part => $value) {
1925
if (strtolower($part) === $key) {
20-
return $value;
26+
if (is_array($value)) {
27+
return reset($value);
28+
} else {
29+
return $value;
30+
}
2131
}
2232
}
2333

2434
return null;
2535
}
2636

37+
/**
38+
* Returns a list of all values for the field with the given $key
39+
*
40+
* @param string $key
41+
* @return array
42+
*/
43+
public function getFieldValues($key)
44+
{
45+
$values = array();
46+
$key = strtolower($key);
47+
48+
foreach ($this->fields as $part => $value) {
49+
if (strtolower($part) === $key) {
50+
if (is_array($value)) {
51+
foreach ($value as $v) {
52+
$values []= $v;
53+
}
54+
} else {
55+
$values []= $value;
56+
}
57+
}
58+
}
59+
60+
return $values;
61+
}
62+
63+
/**
64+
* Returns a hashmap of all variable assignments in the given $key
65+
*
66+
* @param string $key
67+
* @return array
68+
* @uses self::getFieldValues()
69+
*/
70+
public function getFieldVariables($key)
71+
{
72+
$variables = array();
73+
74+
foreach ($this->getFieldValues($key) as $value) {
75+
$temp = explode('=', $value, 2);
76+
$variables[$temp[0]] = $temp[1];
77+
}
78+
79+
return $variables;
80+
}
81+
2782
public function toJson()
2883
{
2984
return json_encode($this->getFields());

src/Protocol/Parser.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,14 @@ private function parseMessage($message)
5454
$key = substr($line, 0, $pos);
5555
}
5656

57-
$fields[$key] = $value;
57+
if (isset($fields[$key])) {
58+
if (!is_array($fields[$key])) {
59+
$fields[$key] = array($fields[$key]);
60+
}
61+
$fields[$key][] = $value;
62+
} else {
63+
$fields[$key] = $value;
64+
}
5865
}
5966

6067
reset($fields);

tests/Protocol/ActionTest.php

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,83 @@ public function testIdCanBeSet()
1616
$action = new Action(array('ActionID' => '123'));
1717

1818
$this->assertEquals('123', $action->getActionId());
19+
20+
$this->assertEquals('123', $action->getFieldValue('ActionID'));
21+
$this->assertEquals('123', $action->getFieldValue('aCtIoNiD'));
22+
23+
$this->assertNull($action->getFieldValue('unknown'));
1924
}
2025

21-
public function testSerializeSimple()
26+
public function testOneFieldValue()
2227
{
2328
$action = new Action(array('Action' => 'name'));
2429

2530
$this->assertEquals("Action: name\r\n\r\n", $action->getMessageSerialized());
31+
32+
$this->assertEquals('name', $action->getFieldValue('Action'));
33+
$this->assertEquals(array('name'), $action->getFieldValues('Action'));
34+
35+
$this->assertEquals(null, $action->getFieldValue('unknown'));
36+
$this->assertEquals(array(), $action->getFieldValues('unknown'));
2637
}
2738

28-
public function testSerializeKeySingle()
39+
public function testMultipleFieldsSingleValue()
2940
{
3041
$action = new Action(array('Action' => 'name', 'Key' => 'Value'));
3142

3243
$this->assertEquals("Action: name\r\nKey: Value\r\n\r\n", $action->getMessageSerialized());
3344
}
3445

35-
public function testSerializeKeyMultipleValues()
46+
public function testOneFieldNoValue()
47+
{
48+
$action = new Action(array('Key' => null));
49+
50+
$this->assertEquals("\r\n", $action->getMessageSerialized());
51+
52+
$this->assertNull($action->getFieldValue('Key'));
53+
$this->assertEquals(array(), $action->getFieldValues('Key'));
54+
}
55+
56+
public function testOneFieldNoValues()
57+
{
58+
$action = new Action(array('Key' => array()));
59+
60+
$this->assertEquals("\r\n", $action->getMessageSerialized());
61+
62+
$this->assertNull($action->getFieldValue('Key'));
63+
$this->assertEquals(array(), $action->getFieldValues('Key'));
64+
}
65+
66+
public function testOneFieldMultipleValues()
3667
{
37-
$action = new Action(array('Action' => 'name', 'Key' => array('Value1', 'Value2')));
68+
$action = new Action(array('Key' => array('Value1', 'Value2')));
3869

39-
$this->assertEquals("Action: name\r\nKey: Value1\r\nKey: Value2\r\n\r\n", $action->getMessageSerialized());
70+
$this->assertEquals("Key: Value1\r\nKey: Value2\r\n\r\n", $action->getMessageSerialized());
71+
72+
$this->assertEquals('Value1', $action->getFieldValue('Key'));
73+
$this->assertEquals(array('Value1', 'Value2'), $action->getFieldValues('Key'));
4074
}
4175

42-
public function testSerializeKeyMultipleKeyValues()
76+
public function testOneFieldMultipleValuesIgnoreNulls()
4377
{
44-
$action = new Action(array('Action' => 'name', 'Variables' => array('first' => 'on', 'second' => 'off')));
78+
$action = new Action(array('Key' => array(null, 'value', null)));
79+
80+
$this->assertEquals("Key: value\r\n\r\n", $action->getMessageSerialized());
81+
82+
$this->assertEquals('value', $action->getFieldValue('Key'));
83+
$this->assertEquals(array('value'), $action->getFieldValues('Key'));
84+
}
85+
86+
public function testOneFieldMultipleKeyValues()
87+
{
88+
$action = new Action(array('Variables' => array('first' => 'on', 'second' => 'off')));
89+
90+
$this->assertEquals("Variables: first=on\r\nVariables: second=off\r\n\r\n", $action->getMessageSerialized());
91+
92+
$this->assertEquals('first=on', $action->getFieldValue('Variables'));
93+
$this->assertEquals(array('first=on', 'second=off'), $action->getFieldValues('Variables'));
4594

46-
$this->assertEquals("Action: name\r\nVariables: first=on\r\nVariables: second=off\r\n\r\n", $action->getMessageSerialized());
95+
$this->assertEquals(array('first' => 'on', 'second' => 'off'), $action->getFieldVariables('Variables'));
96+
$this->assertEquals(array(), $action->getFieldVariables('unknown'));
4797
}
4898
}

tests/Protocol/ParserTest.php

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public function testParseResponse()
1616
/* @var $first Clue\React\Ami\Protocol\Response */
1717

1818
$this->assertInstanceOf('Clue\React\Ami\Protocol\Response', $first);
19-
$this->assertEquals('Success', $first->getField('Response'));
19+
$this->assertEquals('Success', $first->getFieldValue('Response'));
2020
}
2121

2222
public function testParseResponseSpace()
@@ -31,7 +31,7 @@ public function testParseResponseSpace()
3131
/* @var $first Clue\React\Ami\Protocol\Response */
3232

3333
$this->assertInstanceOf('Clue\React\Ami\Protocol\Response', $first);
34-
$this->assertEquals(' spaces ', $first->getField('Message'));
34+
$this->assertEquals(' spaces ', $first->getFieldValue('Message'));
3535
}
3636

3737
public function testParsingMultipleEvents()
@@ -49,6 +49,22 @@ public function testParsingMultipleEvents()
4949
$this->assertEquals('TestA', $first->getName());
5050
}
5151

52+
public function testParseResponseMultipleValues()
53+
{
54+
$parser = new Parser();
55+
$this->assertEquals(array(), $parser->push("Asterisk Call Manager/1.3\r\n"));
56+
57+
$ret = $parser->push("Response: Success\r\nMessage: one\r\nMessage: two\r\n\r\n");
58+
$this->assertCount(1, $ret);
59+
60+
$first = reset($ret);
61+
/* @var $first Clue\React\Ami\Protocol\Response */
62+
63+
$this->assertInstanceOf('Clue\React\Ami\Protocol\Response', $first);
64+
$this->assertEquals('one', $first->getFieldValue('Message'));
65+
$this->assertEquals(array('one', 'two'), $first->getFieldValues('Message'));
66+
}
67+
5268
public function testParsingCommandResponse()
5369
{
5470
$parser = new Parser();
@@ -61,8 +77,8 @@ public function testParsingCommandResponse()
6177
/* @var $first Clue\React\Ami\Protocol\Response */
6278

6379
$this->assertInstanceOf('Clue\React\Ami\Protocol\Response', $first);
64-
$this->assertEquals('Follows', $first->getField('Response'));
65-
$this->assertEquals("Testing: yes\nAnother Line\n--END COMMAND--", $first->getField('_'));
80+
$this->assertEquals('Follows', $first->getFieldValue('Response'));
81+
$this->assertEquals("Testing: yes\nAnother Line\n--END COMMAND--", $first->getFieldValue('_'));
6682
}
6783

6884
/**

0 commit comments

Comments
 (0)