Test Failed
Branch master (6cd10c)
by Robert
02:58
created

LiveEngageLaravel::requestClient()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 22
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 0
cts 15
cp 0
rs 9.2
c 0
b 0
f 0
cc 1
eloc 15
nc 1
nop 0
crap 2
1
<?php
2
3
namespace LivePersonInc\LiveEngageLaravel;
4
5
use Carbon\Carbon;
6
use GuzzleHttp\Client;
7
use GuzzleHttp\HandlerStack;
8
use GuzzleHttp\Subscriber\Oauth\Oauth1;
9
use LivePersonInc\LiveEngageLaravel\Models\Info;
10
use LivePersonInc\LiveEngageLaravel\Models\MetaData;
11
use LivePersonInc\LiveEngageLaravel\Models\MessagingInfo;
12
use LivePersonInc\LiveEngageLaravel\Models\Payload;
13
use LivePersonInc\LiveEngageLaravel\Models\Visitor;
14
use LivePersonInc\LiveEngageLaravel\Models\Agent;
15
use LivePersonInc\LiveEngageLaravel\Models\Campaign;
16
use LivePersonInc\LiveEngageLaravel\Models\Engagement;
17
use LivePersonInc\LiveEngageLaravel\Models\Conversation;
18
use LivePersonInc\LiveEngageLaravel\Collections\EngagementHistory;
19
use LivePersonInc\LiveEngageLaravel\Collections\AgentParticipants;
20
use LivePersonInc\LiveEngageLaravel\Exceptions\LiveEngageException;
21
use LivePersonInc\LiveEngageLaravel\Collections\ConversationHistory;
22
23
class LiveEngageLaravel
24
{
25
	private $account = false;
26
	private $results = [];
27
	private $skills = [];
28
	private $next = false;
29
	private $prev = false;
30
	private $start;
31
	private $end;
32
	private $config = 'services.liveperson.default';
33
	private $version = '1.0';
34
	private $history_limit = 50;
35
	private $history = false;
36
	private $context = 'interactionHistoryRecords';
37
	private $interactive = true;
38
	private $ended = true;
39
	private $bearer = false;
40
41
	private $domain = false;
42
43
	private $retry_limit = 5;
44
	private $retry_counter = 0;
45
46
	public function __get($attribute)
47
	{
48
		return $this->$attribute;
49
	}
50
51
	public function __set($attribute, $value)
52
	{
53
		return $this->$attribute = $value;
54
	}
55
56
	public function __construct()
57
	{
58
		$this->account = config("{$this->config}.account");
59
		//$this->domain = config("{$this->config}.domain");
60
		$this->version = config("{$this->config}.version") ?: $this->version;
61
	}
62
63
	public function key($key = 'default')
64
	{
65
		$this->config = "services.liveperson.$key";
66
67
		return $this;
68
	}
69
	
70
	public function nonInteractive()
71
	{
72
		$this->interactive = false;
73
		return $this;
74
	}
75
	
76
	public function active()
77
	{
78
		$this->ended = false;
79
		return $this;
80
	}
81
82
	public function limit($limit)
83
	{
84
		$this->history_limit = $limit;
85
86
		return $this;
87
	}
88
89
	public function skills($skills)
90
	{
91
		$this->skills = $skills;
92
93
		return $this;
94
	}
95
96
	public function retry($limit)
97
	{
98
		$this->retry_limit = $limit;
99
100
		return $this;
101
	}
102
103
	public function get()
104
	{
105
		return $this->results;
106
	}
107
108
	public function account($accountid)
109
	{
110
		$this->account = $accountid;
111
112
		return $this;
113
	}
114
115
	public function domain($service)
116
	{
117
		$response = $this->requestV1("https://api.liveperson.net/api/account/{$this->account}/service/{$service}/baseURI.json?version={$this->version}", 'GET');
118
		if (is_a($response, 'Exception')) {
0 ignored issues
show
Bug introduced by
It seems like $response can also be of type mixed; however, parameter $object of is_a() does only seem to accept object|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

118
		if (is_a(/** @scrutinizer ignore-type */ $response, 'Exception')) {
Loading history...
119
			throw new \Exception('Unable to get LivePerson account domain', 101);
120
		} else {
121
			$this->domain = $response->baseURI;
122
123
			return $this;
124
		}
125
	}
126
127
	public function visitor($visitorID, $sessionID, $setData = false)
128
	{
129
		$this->domain('smt');
130
131
		if ($setData) {
132
			$url = "https://{$this->domain}/api/account/{$this->account}/monitoring/visitors/{$visitorID}/visits/current/events?v=1&sid={$sessionID}";
133
134
			return $this->requestV1($url, 'POST', $setData);
135
		} else {
136
			$url = "https://{$this->domain}/api/account/{$this->account}/monitoring/visitors/{$visitorID}/visits/current/state?v=1&sid={$sessionID}";
137
138
			return $this->requestV1($url, 'GET');
139
		}
140
	}
141
142
	final public function retrieveHistory(Carbon $start, Carbon $end, $url = false)
143
	{
144
		$this->domain('engHistDomain');
145
146
		$url = $url ?: "https://{$this->domain}/interaction_history/api/account/{$this->account}/interactions/search?limit={$this->history_limit}&offset=0";
147
148
		$start_str = $start->toW3cString();
149
		$end_str = $end->toW3cString();
150
151
		$data = [
152
			'interactive' => $this->interactive,
153
			'ended' => $this->ended,
154
			'start' => [
155
				'from' => strtotime($start_str) . '000',
156
				'to' => strtotime($end_str) . '000',
157
			],
158
		];
159
		if (count($this->skills)) {
160
			$data['skillIds'] = $this->skills;
161
		}
162
163
		$data = new Payload($data);
164
165
		return $this->requestV1($url, 'POST', $data);
166
	}
167
168
	final public function retrieveMsgHistory(Carbon $start, Carbon $end, $url = false)
169
	{
170
		$this->domain('msgHist');
171
172
		$url = $url ?: "https://{$this->domain}/messaging_history/api/account/{$this->account}/conversations/search?limit={$this->history_limit}&offset=0&sort=start:desc";
173
174
		$start_str = $start->toW3cString();
175
		$end_str = $end->toW3cString();
176
177
		$data = [
178
			'status' => $this->ended ? ['CLOSE'] : ['OPEN', 'CLOSE'],
179
			'start' => [
180
				'from' => strtotime($start_str) . '000',
181
				'to' => strtotime($end_str) . '000',
182
			],
183
		];
184
		if (count($this->skills)) {
185
			$data['skillIds'] = $this->skills;
186
		}
187
188
		$data = new Payload($data);
189
190
		return $this->requestV1($url, 'POST', $data);
191
	}
192
	
193
	public function getAgentStatus($skills)
194
	{
195
		$skills = is_array($skills) ? $skills : [$skills];
196
	
197
		$this->domain('msgHist');
198
		
199
		$url = "https://{$this->domain}/messaging_history/api/account/{$this->account}/agent-view/status";
200
		
201
		$data['skillIds'] = $skills;
0 ignored issues
show
Comprehensibility Best Practice introduced by
$data was never initialized. Although not strictly required by PHP, it is generally a good practice to add $data = array(); before regardless.
Loading history...
202
		
203
		$response = $this->requestV1($url, 'POST', $data);
204
		$agents = [];
205
		
206
		foreach ($response->agentStatusRecords as $agent) {
207
			$agents[] = new Agent((array) $agent);
208
		}
209
		
210
		$collection = new AgentParticipants($response->agentStatusRecords);
211
		$collection->metaData = $response->_metadata;
212
		
213
		return $collection;
214
		
215
	}
216
217
	public function messagingHistory(Carbon $start = null, Carbon $end = null)
218
	{
219
		$this->retry_counter = 0;
220
221
		$start = $start ?: (new Carbon())->today();
222
		$end = $end ?: (new Carbon())->today()->addHours(23)->addMinutes(59);
223
224
		$this->start = $start;
225
		$this->end = $end;
226
227
		$results_object = $this->retrieveMsgHistory($start, $end);
228
		
229
		if ($results_object) {
230
		
231
			$meta = new MetaData((array) $results_object->_metadata);
232
			
233
			$collection = new ConversationHistory($results_object->conversationHistoryRecords);
234
			$meta->start = $this->start;
235
			$meta->end = $this->end;
236
			$collection->metaData = $meta;
237
			
238
			return $collection;
239
			
240
		} else {
241
			return false;
242
		}
243
	}
244
245
	public function history(Carbon $start = null, Carbon $end = null)
246
	{
247
		$this->retry_counter = 0;
248
249
		$start = $start ?: (new Carbon())->today();
250
		$end = $end ?: (new Carbon())->today()->addHours(23)->addMinutes(59);
251
252
		$this->start = $start;
253
		$this->end = $end;
254
255
		$results_object = $this->retrieveHistory($start, $end);
256
		
257
		if ($results_object) {
258
		
259
			$meta = new MetaData((array) $results_object->_metadata);
260
			
261
			$collection = new EngagementHistory($results_object->interactionHistoryRecords);
262
			$meta->start = $this->start;
263
			$meta->end = $this->end;
264
			$collection->metaData = $meta;
265
			
266
			return $collection;
267
			
268
		} else {
269
			return false;
270
		}
271
	}
272
	
273
	public function login()
274
	{
275
		$this->domain('agentVep');
276
		
277
		$consumer_key = config("{$this->config}.key");
278
		$consumer_secret = config("{$this->config}.secret");
279
		$token = config("{$this->config}.token");
280
		$secret = config("{$this->config}.token_secret");
281
		$username = config("{$this->config}.user_name");
282
		
283
		$auth = [
284
			'username'		  => $username,
285
			'appKey'			=> $consumer_key,
286
			'secret'			=> $consumer_secret,
287
			'accessToken'		=> $token,
288
			'accessTokenSecret' => $secret,
289
		];
290
		
291
		$url = "https://{$this->domain}/api/account/{$this->account}/login?v=1.3";
292
		
293
		$response = $this->requestV1($url, 'POST', $auth);
294
		
295
		$this->bearer = $response->bearer;
296
		
297
		return $this;
298
	}
299
	
300
	private function requestV2($url, $method, $payload = false)
0 ignored issues
show
Unused Code introduced by
The method requestV2() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
301
	{
302
		if (!$this->bearer) {
303
			$this->login();
304
		}
305
		
306
		$client = new Client();
307
		$args = [
308
			'headers' => [
309
				'Authorization' => $this->bearer
310
			]
311
		];
312
		
313
		if ($payload !== false) {
314
			$args['body'] = json_encode($payload);
315
		}
316
		
317
		try {
318
			$res = $client->request($method, $url, $args);
319
		} catch (\Exception $e) {
320
			throw $e;
321
		} 
322
		
323
		return json_decode($res->getBody());
324
	}
325
	
326
	private function requestClient()
327
	{
328
		$consumer_key = config("{$this->config}.key");
329
		$consumer_secret = config("{$this->config}.secret");
330
		$token = config("{$this->config}.token");
331
		$secret = config("{$this->config}.token_secret");
332
333
		$stack = HandlerStack::create();
334
		$auth = new Oauth1([
335
			'consumer_key'	=> $consumer_key,
336
			'consumer_secret' => $consumer_secret,
337
			'token'		   => $token,
338
			'token_secret'	=> $secret,
339
			'signature_method'=> Oauth1::SIGNATURE_METHOD_HMAC,
340
		]);
341
		$stack->push($auth);
342
343
		$client = new Client([
344
			'handler' => $stack,
345
		]);
346
		
347
		return $client;
348
	}
349
350
	private function requestV1($url, $method, $payload = false)
351
	{
352
		$client = $this->requestClient();
353
354
		$args = [
355
			'auth' => 'oauth',
356
			'headers' => [
357
				'content-type' => 'application/json',
358
			],
359
		];
360
361
		if ($payload !== false) {
362
			$args['body'] = json_encode($payload);
363
		}
364
365
		try {
366
			$res = $client->request($method, $url, $args);
367
368
			$response = json_decode($res->getBody());
369
		} catch (\GuzzleHttp\Exception\ConnectException $connection) {
370
			throw $connection;
371
		} catch (\GuzzleHttp\Exception\ClientException $clientException) {
372
			throw $clientException;
373
		} catch (\Exception $e) {
374
			if ($this->retry_counter < $this->retry_limit || $this->retry_limit == -1) {
375
				usleep(1500);
376
				$this->retry_counter++;
377
				$response = $this->requestV1($url, $payload);
378
			} else {
379
				throw new LiveEngageException("Retry limit has been exceeded ($this->retry_limit)", 100);
380
			}
381
		}
382
383
		return $response;
384
	}
385
}
386