Passed
Branch master (c45254)
by Robert
03:51
created

LiveEngageLaravel::retrieveMsgHistory()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 23
ccs 0
cts 12
cp 0
rs 8.7972
c 0
b 0
f 0
cc 4
eloc 13
nc 4
nop 3
crap 20
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\Humans;
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 Humans($agents);
211
		$collection->metaData = $response->_metadata;
0 ignored issues
show
Bug introduced by
The property metaData does not seem to exist on LivePersonInc\LiveEngageLaravel\Collections\Humans.
Loading history...
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
			$results = array_map(function($item) {
234
				return new Conversation((array) $item);
235
			}, $results_object->conversationHistoryRecords);
236
			
237
			$collection = new ConversationHistory($results);
238
			$meta->start = $this->start;
0 ignored issues
show
Bug introduced by
The property start does not seem to exist on LivePersonInc\LiveEngageLaravel\Models\MetaData. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
239
			$meta->end = $this->end;
0 ignored issues
show
Bug introduced by
The property end does not seem to exist on LivePersonInc\LiveEngageLaravel\Models\MetaData. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
240
			$collection->metaData = $meta;
241
			
242
			return $collection;
243
			
244
		} else {
245
			return false;
246
		}
247
	}
248
249
	public function history(Carbon $start = null, Carbon $end = null)
250
	{
251
		$this->retry_counter = 0;
252
253
		$start = $start ?: (new Carbon())->today();
254
		$end = $end ?: (new Carbon())->today()->addHours(23)->addMinutes(59);
255
256
		$this->start = $start;
257
		$this->end = $end;
258
259
		$results_object = $this->retrieveHistory($start, $end);
260
		
261
		if ($results_object) {
262
		
263
			$meta = new MetaData((array) $results_object->_metadata);
264
			
265
			$results = array_map(function($item) {
266
				return new Engagement((array) $item);
267
			}, $results_object->interactionHistoryRecords);
268
			
269
			$collection = new EngagementHistory($results);
270
			$meta->start = $this->start;
0 ignored issues
show
Bug introduced by
The property start does not seem to exist on LivePersonInc\LiveEngageLaravel\Models\MetaData. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
271
			$meta->end = $this->end;
0 ignored issues
show
Bug introduced by
The property end does not seem to exist on LivePersonInc\LiveEngageLaravel\Models\MetaData. Are you sure there is no database migration missing?

Checks if undeclared accessed properties appear in database migrations and if the creating migration is correct.

Loading history...
272
			$collection->metaData = $meta;
273
			
274
			return $collection;
275
			
276
		} else {
277
			return false;
278
		}
279
	}
280
	
281
	public function login()
282
	{
283
		$this->domain('agentVep');
284
		
285
		$consumer_key = config("{$this->config}.key");
286
		$consumer_secret = config("{$this->config}.secret");
287
		$token = config("{$this->config}.token");
288
		$secret = config("{$this->config}.token_secret");
289
		$username = config("{$this->config}.user_name");
290
		
291
		$auth = [
292
			'username'		  => $username,
293
			'appKey'			=> $consumer_key,
294
			'secret'			=> $consumer_secret,
295
			'accessToken'		=> $token,
296
			'accessTokenSecret' => $secret,
297
		];
298
		
299
		$url = "https://{$this->domain}/api/account/{$this->account}/login?v=1.3";
300
		
301
		$response = $this->requestV1($url, 'POST', $auth);
302
		
303
		$this->bearer = $response->bearer;
304
		
305
		return $this;
306
	}
307
	
308
	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...
309
	{
310
		if (!$this->bearer) {
311
			$this->login();
312
		}
313
		
314
		$client = new Client();
315
		$args = [
316
			'headers' => [
317
				'Authorization' => $this->bearer
318
			]
319
		];
320
		
321
		if ($payload !== false) {
322
			$args['body'] = json_encode($payload);
323
		}
324
		
325
		try {
326
			$res = $client->request($method, $url, $args);
327
		} catch (\Exception $e) {
328
			throw $e;
329
		} 
330
		
331
		return json_decode($res->getBody());
332
	}
333
334
	private function requestV1($url, $method, $payload = false)
335
	{
336
		$consumer_key = config("{$this->config}.key");
337
		$consumer_secret = config("{$this->config}.secret");
338
		$token = config("{$this->config}.token");
339
		$secret = config("{$this->config}.token_secret");
340
341
		$stack = HandlerStack::create();
342
		$auth = new Oauth1([
343
			'consumer_key'	=> $consumer_key,
344
			'consumer_secret' => $consumer_secret,
345
			'token'		   => $token,
346
			'token_secret'	=> $secret,
347
			'signature_method'=> Oauth1::SIGNATURE_METHOD_HMAC,
348
		]);
349
		$stack->push($auth);
350
351
		$client = new Client([
352
			'handler' => $stack,
353
		]);
354
355
		$args = [
356
			'auth' => 'oauth',
357
			'headers' => [
358
				'content-type' => 'application/json',
359
			],
360
		];
361
362
		if ($payload !== false) {
363
			$args['body'] = json_encode($payload);
364
		}
365
366
		try {
367
			$res = $client->request($method, $url, $args);
368
369
			$response = json_decode($res->getBody());
370
		} catch (\GuzzleHttp\Exception\ConnectException $connection) {
371
			throw $connection;
372
		} catch (\GuzzleHttp\Exception\ClientException $clientException) {
373
			throw $clientException;
374
		} catch (\Exception $e) {
375
			if ($this->retry_counter < $this->retry_limit || $this->retry_limit == -1) {
376
				usleep(1500);
377
				$this->retry_counter++;
378
				$response = $this->requestV1($url, $payload);
379
			} else {
380
				throw new LiveEngageException("Retry limit has been exceeded ($this->retry_limit)", 100);
381
			}
382
		}
383
384
		return $response;
385
	}
386
}
387