Passed
Branch master (7757e2)
by Robert
05:22
created

LiveEngageLaravel::requestV1()   C

Complexity

Conditions 7
Paths 18

Size

Total Lines 34
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 18.1823

Importance

Changes 0
Metric Value
dl 0
loc 34
ccs 7
cts 18
cp 0.3889
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 22
nc 18
nop 3
crap 18.1823
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 1
	public function __get($attribute)
47
	{
48 1
		return $this->$attribute;
49
	}
50
51
	public function __set($attribute, $value)
52
	{
53
		return $this->$attribute = $value;
54
	}
55
56 1
	public function __construct()
57
	{
58 1
		$this->account = config("{$this->config}.account");
59
		//$this->domain = config("{$this->config}.domain");
60 1
		$this->version = config("{$this->config}.version") ?: $this->version;
61 1
	}
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 1
	public function domain($service)
116
	{
117 1
		$response = $this->requestV1("https://api.liveperson.net/api/account/{$this->account}/service/{$service}/baseURI.json?version={$this->version}", 'GET');
118 1
		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 1
			$this->domain = $response->baseURI;
122
123 1
			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 1
	public function getAgentStatus($skills)
194
	{
195 1
		$skills = is_array($skills) ? $skills : [$skills];
196
	
197 1
		$this->domain('msgHist');
198
		
199 1
		$url = "https://{$this->domain}/messaging_history/api/account/{$this->account}/agent-view/status";
200
		
201 1
		$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 1
		$response = $this->requestV1($url, 'POST', $data);
204 1
		$collection = new AgentParticipants($response->agentStatusRecords);
205 1
		$collection->metaData = new MetaData((array) $response->_metadata);
206
		
207 1
		return $collection;
208
		
209
	}
210
211 1
	public function messagingHistory(Carbon $start = null, Carbon $end = null)
212
	{
213 1
		$this->retry_counter = 0;
214
215 1
		$start = $start ?: (new Carbon())->today();
216 1
		$end = $end ?: (new Carbon())->today()->addHours(23)->addMinutes(59);
217
218 1
		$this->start = $start;
219 1
		$this->end = $end;
220
221 1
		$results_object = $this->retrieveMsgHistory($start, $end);
222
		
223 1
		if ($results_object) {
224
		
225 1
			$results_object->_metadata->start = $this->start;
226 1
			$results_object->_metadata->end = $this->end;
227
		
228 1
			$meta = new MetaData((array) $results_object->_metadata);
229
			
230 1
			$collection = new ConversationHistory($results_object->conversationHistoryRecords);
231 1
			$collection->metaData = $meta;
232
			
233 1
			return $collection;
234
			
235
		} else {
236
			return false;
237
		}
238
	}
239
240 1
	public function history(Carbon $start = null, Carbon $end = null)
241
	{
242 1
		$this->retry_counter = 0;
243
244 1
		$start = $start ?: (new Carbon())->today();
245 1
		$end = $end ?: (new Carbon())->today()->addHours(23)->addMinutes(59);
246
247 1
		$this->start = $start;
248 1
		$this->end = $end;
249
250 1
		$results_object = $this->retrieveHistory($start, $end);
251
		
252 1
		if ($results_object) {
253
		
254 1
			$results_object->_metadata->start = $this->start;
255 1
			$results_object->_metadata->end = $this->end;
256
		
257 1
			$meta = new MetaData((array) $results_object->_metadata);
258
			
259 1
			$collection = new EngagementHistory($results_object->interactionHistoryRecords);
260 1
			$collection->metaData = $meta;
261
			
262 1
			return $collection;
263
			
264
		} else {
265
			return false;
266
		}
267
	}
268
	
269
	public function login()
270
	{
271
		$this->domain('agentVep');
272
		
273
		$consumer_key = config("{$this->config}.key");
274
		$consumer_secret = config("{$this->config}.secret");
275
		$token = config("{$this->config}.token");
276
		$secret = config("{$this->config}.token_secret");
277
		$username = config("{$this->config}.user_name");
278
		
279
		$auth = [
280
			'username'		  => $username,
281
			'appKey'			=> $consumer_key,
282
			'secret'			=> $consumer_secret,
283
			'accessToken'		=> $token,
284
			'accessTokenSecret' => $secret,
285
		];
286
		
287
		$url = "https://{$this->domain}/api/account/{$this->account}/login?v=1.3";
288
		
289
		$response = $this->requestV1($url, 'POST', $auth);
290
		
291
		$this->bearer = $response->bearer;
292
		
293
		return $this;
294
	}
295
	
296
	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...
297
	{
298
		if (!$this->bearer) {
299
			$this->login();
300
		}
301
		
302
		$client = new Client();
303
		$args = [
304
			'headers' => [
305
				'Authorization' => $this->bearer
306
			]
307
		];
308
		
309
		if ($payload !== false) {
310
			$args['body'] = json_encode($payload);
311
		}
312
		
313
		try {
314
			$res = $client->request($method, $url, $args);
315
		} catch (\Exception $e) {
316
			throw $e;
317
		} 
318
		
319
		return json_decode($res->getBody());
320
	}
321
	
322 1
	private function requestClient()
323
	{
324 1
		$consumer_key = config("{$this->config}.key");
325 1
		$consumer_secret = config("{$this->config}.secret");
326 1
		$token = config("{$this->config}.token");
327 1
		$secret = config("{$this->config}.token_secret");
328
329 1
		$stack = HandlerStack::create();
330 1
		$auth = new Oauth1([
331 1
			'consumer_key'	=> $consumer_key,
332 1
			'consumer_secret' => $consumer_secret,
333 1
			'token'		   => $token,
334 1
			'token_secret'	=> $secret,
335 1
			'signature_method'=> Oauth1::SIGNATURE_METHOD_HMAC,
336
		]);
337 1
		$stack->push($auth);
338
339 1
		$client = new Client([
340 1
			'handler' => $stack,
341
		]);
342
		
343 1
		return $client;
344
	}
345
346 1
	private function requestV1($url, $method, $payload = false)
347
	{
348 1
		$client = $this->requestClient();
349
350
		$args = [
351 1
			'auth' => 'oauth',
352
			'headers' => [
353
				'content-type' => 'application/json',
354
			],
355
		];
356
357 1
		if ($payload !== false) {
358
			$args['body'] = json_encode($payload);
359
		}
360
361
		try {
362 1
			$res = $client->request($method, $url, $args);
363
364 1
			$response = json_decode($res->getBody());
365
		} catch (\GuzzleHttp\Exception\ConnectException $connection) {
366
			throw $connection;
367
		} catch (\GuzzleHttp\Exception\ClientException $clientException) {
368
			throw $clientException;
369
		} catch (\Exception $e) {
370
			if ($this->retry_counter < $this->retry_limit || $this->retry_limit == -1) {
371
				usleep(1500);
372
				$this->retry_counter++;
373
				$response = $this->requestV1($url, $payload);
374
			} else {
375
				throw new LiveEngageException("Retry limit has been exceeded ($this->retry_limit)", 100);
376
			}
377
		}
378
379 1
		return $response;
380
	}
381
}
382