AriClient   A
last analyzed

Complexity

Total Complexity 36

Size/Duplication

Total Lines 357
Duplicated Lines 0 %

Coupling/Cohesion

Components 12
Dependencies 17

Test Coverage

Coverage 88.7%

Importance

Changes 0
Metric Value
wmc 36
lcom 12
cbo 17
dl 0
loc 357
ccs 102
cts 115
cp 0.887
rs 9.52
c 0
b 0
f 0

22 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A connect() 0 51 4
A onRequest() 0 4 1
A onHandshake() 0 4 1
A onConnect() 0 4 1
A onClose() 0 4 1
A getWsClient() 0 4 1
A getEventLoop() 0 4 1
A getLogger() 0 4 1
A getStasisApplicationName() 0 4 1
A getEndpoint() 0 4 1
A applications() 0 8 2
A asterisk() 0 8 2
A bridges() 0 8 2
A channels() 0 8 2
A deviceStates() 0 8 2
A endPoints() 0 8 2
A events() 0 8 2
A mailboxes() 0 8 2
A playbacks() 0 8 2
A recordings() 0 8 2
A sounds() 0 8 2
1
<?php
2
3
/*
4
 * Copyright 2015 Brian Smith <[email protected]>.
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *      http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
19
namespace phparia\Client;
20
21
use Devristo\Phpws\Client\WebSocket;
22
use Devristo\Phpws\Messaging\WebSocketMessage;
23
use GuzzleHttp\Client;
24
use phparia\Api\Applications;
25
use phparia\Api\Asterisk;
26
use phparia\Api\Bridges;
27
use phparia\Api\Channels;
28
use phparia\Api\DeviceStates;
29
use phparia\Api\Endpoints;
30
use phparia\Api\Events;
31
use phparia\Api\Mailboxes;
32
use phparia\Api\Playbacks;
33
use phparia\Api\Recordings;
34
use phparia\Api\Sounds;
35
use phparia\Events\IdentifiableEventInterface;
36
use phparia\Events\Message;
37
use React\EventLoop\LoopInterface;
38
use Zend\Log\LoggerInterface;
39
40
/**
41
 * @author Brian Smith <[email protected]>
42
 */
43
class AriClient
44
{
45
46
    /**
47
     * @var WebSocket
48
     */
49
    protected $wsClient;
50
51
    /**
52
     * @var LoopInterface
53
     */
54
    protected $eventLoop;
55
56
    /**
57
     * @var LoggerInterface
58
     */
59
    protected $logger;
60
61
    /**
62
     * @var string
63
     */
64
    protected $stasisApplicationName;
65
66
    /**
67
     * @var Client
68
     */
69
    protected $endpoint;
70
71
    /**
72
     * @var Applications
73
     */
74
    protected $applications;
75
76
    /**
77
     * @var Asterisk
78
     */
79
    protected $asterisk;
80
81
    /**
82
     * @var Bridges
83
     */
84
    protected $bridges;
85
86
    /**
87
     * @var Channels
88
     */
89
    protected $channels;
90
91
    /**
92
     * @var DeviceStates
93
     */
94
    protected $deviceStates;
95
96
    /**
97
     * @var Endpoints
98
     */
99
    protected $endPoints;
100
101
    /**
102
     * @var Events
103
     */
104
    protected $events;
105
106
    /**
107
     * @var Mailboxes
108
     */
109
    protected $mailboxes;
110
111
    /**
112
     * @var Playbacks
113
     */
114
    protected $playbacks;
115
116
    /**
117
     * @var Recordings
118
     */
119
    protected $recordings;
120
121
    /**
122
     * @var Sounds
123
     */
124
    protected $sounds;
125
126 88
    public function __construct(LoopInterface $eventLoop, LoggerInterface $logger)
127
    {
128 88
        $this->eventLoop = $eventLoop;
129 88
        $this->logger = $logger;
130 88
    }
131
132
    /**
133
     * Connect to ARI.
134
     *
135
     * @param string $address Example ws://localhost:8088/ari/events?api_key=username:password&app=stasis_app_name
136
     * @param array $streamOptions Such as ['ssl' => ['verify_peer' => false, 'verify_peer_name' => false]];
137
     * @param array $httpOptions Such as ['verify' => false];
138
     */
139 88
    public function connect($address, array $streamOptions = [], $httpOptions = [])
140
    {
141 88
        $components = parse_url($address);
142 88
        $scheme = $components['scheme'];
143 88
        $host = $components['host'];
144 88
        $port = $components['port'];
145 88
        $path = $components['path'];
146 88
        $query = $components['query'];
147 88
        $queryParts = [];
148 88
        parse_str($query, $queryParts);
149
150 88
        $this->stasisApplicationName = $queryParts['app'];
151 88
        $apiKey = $queryParts['api_key'];
152 88
        list($username, $password) = explode(':', $apiKey);
153
154
        $config = [
155 88
            'base_uri' => ($scheme === 'wss' ? 'https://' : 'http://').$host.':'.$port.dirname($path).'/',
156 88
            'auth' => [$username, $password],
157
            'verify' => false
158 88
        ];
159 88
        $config = array_merge($config, $httpOptions);
160
        
161 88
        $this->endpoint = new Client($config);
162
163 88
        $this->wsClient = new WebSocket($address, $this->eventLoop, $this->logger, $streamOptions);
164
165 88
        $this->wsClient->on("message", function (WebSocketMessage $rawMessage) {
166
            $message = new Message($rawMessage->getData());
167
168
            $eventType = '\\phparia\\Events\\'.$message->getType();
169
            if (class_exists($eventType)) {
170
                $event = new $eventType($this, $rawMessage->getData());
171
            } else {
172
                $this->logger->warn("Event: '$eventType' not implemented");
173
174
                // @todo Create a generic event for any that are not implemented
175
176
                return;
177
            }
178
179
            // Emit the specific event (just to get it back to where it came from)
180
            if ($event instanceof IdentifiableEventInterface) {
181
                $this->logger->notice("Emitting ID event: {$event->getEventId()}");
182
                $this->wsClient->emit($event->getEventId(), array('event' => $event));
183
            }
184
185
            // Emit the general event
186
            $this->logger->notice("Emitting event: {$message->getType()}");
187
            $this->wsClient->emit($message->getType(), array('event' => $event));
188 88
        });
189 88
    }
190
191
    /**
192
     * Headers will be passed to the provided callback on request
193
     *
194
     * @param callable $callback
195
     */
196 1
    public function onRequest(callable $callback)
197
    {
198 1
        $this->wsClient->on("request", $callback);
199 1
    }
200
201
    /**
202
     * Handshake will be passed to the provide callback on handshake
203
     *
204
     * @param callable $callback
205
     */
206 1
    public function onHandshake(callable $callback)
207
    {
208 1
        $this->wsClient->on("handshake", $callback);
209 1
    }
210
211
    /**
212
     * @param callable|callable $callback
213
     */
214 40
    public function onConnect(callable $callback)
215
    {
216 40
        $this->wsClient->on("connect", $callback);
217 40
    }
218
219
    /**
220
     * @param callable|callable $callback
221
     */
222 1
    public function onClose(callable $callback)
223
    {
224 1
        $this->wsClient->on("close", $callback);
225 1
    }
226
227
    /**
228
     * @return WebSocket
229
     */
230 88
    public function getWsClient()
231
    {
232 88
        return $this->wsClient;
233
    }
234
235
    /**
236
     * @return LoopInterface
237
     */
238 1
    public function getEventLoop()
239
    {
240 1
        return $this->eventLoop;
241
    }
242
243
    /**
244
     * @return LoggerInterface
245
     */
246 1
    public function getLogger()
247
    {
248 1
        return $this->logger;
249
    }
250
251
    /**
252
     * @return string
253
     */
254 88
    public function getStasisApplicationName()
255
    {
256 88
        return $this->stasisApplicationName;
257
    }
258
259
    /**
260
     * @return Client
261
     */
262 88
    public function getEndpoint()
263
    {
264 88
        return $this->endpoint;
265
    }
266
267
    /**
268
     * @return Applications
269
     */
270 1
    public function applications()
271
    {
272 1
        if (!$this->applications instanceof Applications) {
273 1
            $this->applications = new Applications($this);
274 1
        }
275
276 1
        return $this->applications;
277
    }
278
279
    /**
280
     * @return Asterisk
281
     */
282 6
    public function asterisk()
283
    {
284 6
        if (!$this->asterisk instanceof Asterisk) {
285 6
            $this->asterisk = new Asterisk($this);
286 6
        }
287
288 6
        return $this->asterisk;
289
    }
290
291
    /**
292
     * @return Bridges
293
     */
294 17
    public function bridges()
295
    {
296 17
        if (!$this->bridges instanceof Bridges) {
297 17
            $this->bridges = new Bridges($this);
298 17
        }
299
300 17
        return $this->bridges;
301
    }
302
303
    /**
304
     * @return Channels
305
     */
306 88
    public function channels()
307
    {
308 88
        if (!$this->channels instanceof Channels) {
309 88
            $this->channels = new Channels($this);
310 88
        }
311
312 88
        return $this->channels;
313
    }
314
315
    /**
316
     * @return DeviceStates
317
     */
318 1
    public function deviceStates()
319
    {
320 1
        if (!$this->deviceStates instanceof DeviceStates) {
321 1
            $this->deviceStates = new DeviceStates($this);
322 1
        }
323
324 1
        return $this->deviceStates;
325
    }
326
327
    /**
328
     * @return Endpoints
329
     */
330 2
    public function endPoints()
331
    {
332 2
        if (!$this->endPoints instanceof Endpoints) {
333 2
            $this->endPoints = new Endpoints($this);
334 2
        }
335
336 2
        return $this->endPoints;
337
    }
338
339
    /**
340
     * @return Events
341
     */
342 1
    public function events()
343
    {
344 1
        if (!$this->events instanceof Events) {
345 1
            $this->events = new Events($this);
346 1
        }
347
348 1
        return $this->events;
349
    }
350
351
    /**
352
     * @return Mailboxes
353
     */
354 1
    public function mailboxes()
355
    {
356 1
        if (!$this->mailboxes instanceof Mailboxes) {
357 1
            $this->mailboxes = new Mailboxes($this);
358 1
        }
359
360 1
        return $this->mailboxes;
361
    }
362
363
    /**
364
     * @return Playbacks
365
     */
366 1
    public function playbacks()
367
    {
368 1
        if (!$this->playbacks instanceof Playbacks) {
369 1
            $this->playbacks = new Playbacks($this);
370 1
        }
371
372 1
        return $this->playbacks;
373
    }
374
375
    /**
376
     * @return Recordings
377
     */
378 5
    public function recordings()
379
    {
380 5
        if (!$this->recordings instanceof Recordings) {
381 5
            $this->recordings = new Recordings($this);
382 5
        }
383
384 5
        return $this->recordings;
385
    }
386
387
    /**
388
     * @return Sounds
389
     */
390 3
    public function sounds()
391
    {
392 3
        if (!$this->sounds instanceof Sounds) {
393 3
            $this->sounds = new Sounds($this);
394 3
        }
395
396 3
        return $this->sounds;
397
    }
398
399
}
400