Skip to content

Commit 3b21db7

Browse files
authored
Merge pull request #55 from clue-labs/docs
Improve README and API documentation
2 parents 6169f01 + a1eb1f2 commit 3b21db7

9 files changed

Lines changed: 562 additions & 101 deletions

File tree

README.md

Lines changed: 214 additions & 86 deletions
Large diffs are not rendered by default.

src/ActionSender.php

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,19 @@
22

33
namespace Clue\React\Ami;
44

5-
use Clue\React\Ami\Client;
65
use Clue\React\Ami\Protocol\Collection;
76
use Clue\React\Ami\Protocol\Event;
87
use Clue\React\Ami\Protocol\Response;
98
use React\Promise\Deferred;
109

10+
/**
11+
* The `ActionSender` wraps a given [`Client`](#client) instance to provide a simple way to execute common actions.
12+
* This class represents the main interface to execute actions and wait for the corresponding responses.
13+
*
14+
* ```php
15+
* $sender = new Clue\React\Ami\ActionSender($client);
16+
* ```
17+
*/
1118
class ActionSender
1219
{
1320
private $client;
@@ -17,33 +24,64 @@ public function __construct(Client $client)
1724
$this->client = $client;
1825
}
1926

27+
/**
28+
* @param string $username
29+
* @param string $secret
30+
* @param ?bool $events
31+
* @return \React\Promise\PromiseInterface<Response,\Exception>
32+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_Login
33+
*/
2034
public function login($username, $secret, $events = null)
2135
{
2236
$events = $this->boolParam($events);
2337
return $this->request('Login', array('UserName' => $username, 'Secret' => $secret, 'Events' => $events));
2438
}
2539

40+
/**
41+
* @return \React\Promise\PromiseInterface<Response,\Exception>
42+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_Logoff
43+
*/
2644
public function logoff()
2745
{
2846
return $this->request('Logoff');
2947
}
3048

49+
/**
50+
* @param string $agentId
51+
* @param bool $soft
52+
* @return \React\Promise\PromiseInterface<Response,\Exception>
53+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_AgentLogoff
54+
*/
3155
public function agentLogoff($agentId, $soft = false)
3256
{
3357
$bool = $soft ? 'true' : 'false';
3458
return $this->request('AgentLogoff', array('Agent' => $agentId, 'Soft' => $bool));
3559
}
3660

61+
/**
62+
* @return \React\Promise\PromiseInterface<Response,\Exception>
63+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_Ping
64+
*/
3765
public function ping()
3866
{
3967
return $this->request('Ping');
4068
}
4169

70+
/**
71+
* @param string $command
72+
* @return \React\Promise\PromiseInterface<Response,\Exception>
73+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_Command
74+
*/
4275
public function command($command)
4376
{
4477
return $this->request('Command', array('Command' => $command));
4578
}
4679

80+
/**
81+
* @param bool|string[] $eventMask
82+
* @return \React\Promise\PromiseInterface<Response,\Exception>
83+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_Events
84+
*/
4785
public function events($eventMask)
4886
{
4987
if ($eventMask === false) {
@@ -57,62 +95,99 @@ public function events($eventMask)
5795
return $this->request('Events', array('EventMask' => $eventMask));
5896
}
5997

98+
/**
99+
* @param string $peerName
100+
* @return \React\Promise\PromiseInterface<Response,\Exception>
101+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_SIPshowpeer
102+
*/
60103
public function sipShowPeer($peerName)
61104
{
62105
return $this->request('SIPshowpeer', array('Peer' => $peerName));
63106
}
64107

108+
/**
109+
* @return \React\Promise\PromiseInterface<Response,\Exception>
110+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_ListCommands
111+
*/
65112
public function listCommands()
66113
{
67114
return $this->request('ListCommands');
68115
}
69116

117+
/**
118+
* @param string $channel
119+
* @param string $message
120+
* @return \React\Promise\PromiseInterface<Response,\Exception>
121+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_SendText
122+
*/
70123
public function sendText($channel, $message)
71124
{
72125
return $this->request('Sendtext', array('Channel' => $channel, 'Message' => $message));
73126
}
74127

128+
/**
129+
* @param string $channel
130+
* @param int $cause
131+
* @return \React\Promise\PromiseInterface<Response,\Exception>
132+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_Hangup
133+
*/
75134
public function hangup($channel, $cause)
76135
{
77136
return $this->request('Hangup', array('Channel' => $channel, 'Cause' => $cause));
78137
}
79138

139+
/**
140+
* @param string $authType
141+
* @return \React\Promise\PromiseInterface<Response,\Exception>
142+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_Challenge
143+
*/
80144
public function challenge($authType = 'MD5')
81145
{
82146
return $this->request('Challenge', array('AuthType' => $authType));
83147
}
84148

149+
/**
150+
* @param string $filename
151+
* @param ?string $category
152+
* @return \React\Promise\PromiseInterface<Response,\Exception>
153+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_GetConfig
154+
*/
85155
public function getConfig($filename, $category = null)
86156
{
87157
return $this->request('GetConfig', array('Filename' => $filename, 'Category' => $category));
88158
}
89159

90160
/**
91-
* @return \React\Promise\PromiseInterface Promise<Collection> collection with "Event: CoreShowChannel"
161+
* @return \React\Promise\PromiseInterface<Collection,\Exception> collection with "Event: CoreShowChannel"
162+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_CoreShowChannels
92163
*/
93164
public function coreShowChannels()
94165
{
95166
return $this->collectEvents('CoreShowChannels', 'CoreShowChannelsComplete');
96167
}
97168

98169
/**
99-
*
100-
* @return \React\Promise\PromiseInterface Promise<Collection> collection with "Event: PeerEntry"
170+
* @return \React\Promise\PromiseInterface<Collection,\Exception> collection with "Event: PeerEntry"
171+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_SIPpeers
101172
*/
102173
public function sipPeers()
103174
{
104175
return $this->collectEvents('SIPPeers', 'PeerlistComplete');
105176
}
106177

107178
/**
108-
*
109-
* @return \React\Promise\PromiseInterface Promise<Collection> collection with "Event: Agents"
179+
* @return \React\Promise\PromiseInterface<Collection,\Exception>collection with "Event: Agents"
180+
* @link https://wiki.asterisk.org/wiki/display/AST/Asterisk+14+ManagerAction_Agents
110181
*/
111182
public function agents()
112183
{
113184
return $this->collectEvents('Agents', 'AgentsComplete');
114185
}
115186

187+
/**
188+
* @param mixed $value
189+
* @return ?string
190+
*/
116191
private function boolParam($value)
117192
{
118193
if ($value === true) {
@@ -124,11 +199,21 @@ private function boolParam($value)
124199
return null;
125200
}
126201

202+
/**
203+
* @param string $name
204+
* @param array $args
205+
* @return \React\Promise\PromiseInterface<Response,\Exception>
206+
*/
127207
private function request($name, array $args = array())
128208
{
129209
return $this->client->request($this->client->createAction($name, $args));
130210
}
131211

212+
/**
213+
* @param string $command
214+
* @param string $expectedEndEvent
215+
* @return \React\Promise\PromiseInterface<Collection,\Exception>
216+
*/
132217
private function collectEvents($command, $expectedEndEvent)
133218
{
134219
$req = $this->client->createAction($command);

src/Client.php

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,15 @@
1414
use Exception;
1515
use UnexpectedValueException;
1616

17+
/**
18+
* The `Client` is responsible for exchanging messages with the Asterisk Manager Interface
19+
* and keeps track of pending actions.
20+
*
21+
* If you want to send outgoing actions, see below for the [`ActionSender`](#actionsender) class.
22+
*
23+
* Besides defining a few methods, this interface also implements the
24+
* `EventEmitterInterface` which allows you to react to certain events as documented below.
25+
*/
1726
class Client extends EventEmitter
1827
{
1928
private $stream;
@@ -49,6 +58,27 @@ public function __construct(ConnectionInterface $stream, Parser $parser = null)
4958
$this->stream->on('close', array ($that, 'close'));
5059
}
5160

61+
/**
62+
* Queue the given messages to be sent via AMI
63+
* and wait for a [`Response`](#response) object that matches the value of its "ActionID" field.
64+
*
65+
* This method is considered advanced usage and mostly used internally only.
66+
* Creating [`Action`](#action) objects, sending them via AMI and waiting
67+
* for incoming [`Response`](#response) objects is usually hidden behind the
68+
* [`ActionSender`](#actionsender) interface.
69+
*
70+
* If you happen to need a custom or otherwise unsupported action, you can
71+
* also do so manually as follows. Consider filing a PR to add new actions
72+
* to the [`ActionSender`](#actionsender).
73+
*
74+
* ```php
75+
* $action = $client->createAction('Originate', array('Channel' => …));
76+
* $promise = $client->request($action);
77+
* ```
78+
*
79+
* @param Action $message
80+
* @return \React\Promise\PromiseInterface<Response,\Exception>
81+
*/
5282
public function request(Action $message)
5383
{
5484
$deferred = new Deferred();
@@ -91,6 +121,11 @@ public function handleMessage(Message $message)
91121
}
92122
}
93123

124+
/**
125+
* Force-close the AMI connection and reject all pending actions.
126+
*
127+
* @return void
128+
*/
94129
public function close()
95130
{
96131
if ($this->stream === null) {
@@ -112,6 +147,11 @@ public function close()
112147
$this->pending = array();
113148
}
114149

150+
/**
151+
* Soft-close the AMI connection once all pending actions are completed.
152+
*
153+
* @return void
154+
*/
115155
public function end()
116156
{
117157
$this->ending = true;
@@ -126,6 +166,30 @@ public function isBusy()
126166
return !!$this->pending;
127167
}
128168

169+
/**
170+
* Construct a custom AMI action.
171+
*
172+
* This method is considered advanced usage and mostly used internally only.
173+
* Creating [`Action`](#action) objects, sending them via AMI and waiting
174+
* for incoming [`Response`](#response) objects is usually hidden behind the
175+
* [`ActionSender`](#actionsender) interface.
176+
*
177+
* If you happen to need a custom or otherwise unsupported action, you can
178+
* also do so manually as follows. Consider filing a PR to add new actions
179+
* to the [`ActionSender`](#actionsender).
180+
*
181+
* A unique value will be added to "ActionID" field automatically (needed to
182+
* match the incoming responses).
183+
*
184+
* ```php
185+
* $action = $client->createAction('Originate', array('Channel' => …));
186+
* $promise = $client->request($action);
187+
* ```
188+
*
189+
* @param string $name
190+
* @param array $args
191+
* @return Action
192+
*/
129193
public function createAction($name, array $args = array())
130194
{
131195
$args = array('Action' => $name, 'ActionID' => (string)++$this->actionId) + $args;

0 commit comments

Comments
 (0)