Passed
Push — master ( f9e29f...dc59a3 )
by Robert
07:33
created

LiveEngageLaravel::active()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 3
cp 0
rs 10
c 0
b 0
f 0
cc 1
eloc 2
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 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
		$agents = [];
205
		
206 1
		foreach ($response->agentStatusRecords as $agent) {
207 1
			$agents[] = new Agent((array) $agent);
208
		}
209
		
210 1
		$collection = new AgentParticipants($response->agentStatusRecords);
211 1
		$collection->metaData = $response->_metadata;
212
		
213 1
		return $collection;
214
		
215
	}
216
217 1
	public function messagingHistory(Carbon $start = null, Carbon $end = null)
218
	{
219 1
		$this->retry_counter = 0;
220
221 1
		$start = $start ?: (new Carbon())->today();
222 1
		$end = $end ?: (new Carbon())->today()->addHours(23)->addMinutes(59);
223
224 1
		$this->start = $start;
225 1
		$this->end = $end;
226
227 1
		$results_object = $this->retrieveMsgHistory($start, $end);
228
		
229 1
		if ($results_object) {
230
		
231 1
			$meta = new MetaData((array) $results_object->_metadata);
232
			
233 1
			$collection = new ConversationHistory($results_object->conversationHistoryRecords);
234 1
			$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...
235 1
			$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...
236 1
			$collection->metaData = $meta;
237
			
238 1
			return $collection;
239
			
240
		} else {
241
			return false;
242
		}
243
	}
244
245 1
	public function history(Carbon $start = null, Carbon $end = null)
246
	{
247 1
		$this->retry_counter = 0;
248
249 1
		$start = $start ?: (new Carbon())->today();
250 1
		$end = $end ?: (new Carbon())->today()->addHours(23)->addMinutes(59);
251
252 1
		$this->start = $start;
253 1
		$this->end = $end;
254
255 1
		$results_object = $this->retrieveHistory($start, $end);
256
		
257 1
		if ($results_object) {
258
		
259 1
			$results_object->_metadata->start = $this->start;
260 1
			$results_object->_metadata->end = $this->end;
261
		
262 1
			$meta = new MetaData((array) $results_object->_metadata);
263
			
264 1
			$collection = new EngagementHistory($results_object->interactionHistoryRecords);
265 1
			$collection->metaData = $meta;
266
			
267 1
			return $collection;
268
			
269
		} else {
270
			return false;
271
		}
272
	}
273
	
274
	public function login()
275
	{
276
		$this->domain('agentVep');
277
		
278
		$consumer_key = config("{$this->config}.key");
279
		$consumer_secret = config("{$this->config}.secret");
280
		$token = config("{$this->config}.token");
281
		$secret = config("{$this->config}.token_secret");
282
		$username = config("{$this->config}.user_name");
283
		
284
		$auth = [
285
			'username'		  => $username,
286
			'appKey'			=> $consumer_key,
287
			'secret'			=> $consumer_secret,
288
			'accessToken'		=> $token,
289
			'accessTokenSecret' => $secret,
290
		];
291
		
292
		$url = "https://{$this->domain}/api/account/{$this->account}/login?v=1.3";
293
		
294
		$response = $this->requestV1($url, 'POST', $auth);
295
		
296
		$this->bearer = $response->bearer;
297
		
298
		return $this;
299
	}
300
	
301
	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...
302
	{
303
		if (!$this->bearer) {
304
			$this->login();
305
		}
306
		
307
		$client = new Client();
308
		$args = [
309
			'headers' => [
310
				'Authorization' => $this->bearer
311
			]
312
		];
313
		
314
		if ($payload !== false) {
315
			$args['body'] = json_encode($payload);
316
		}
317
		
318
		try {
319
			$res = $client->request($method, $url, $args);
320
		} catch (\Exception $e) {
321
			throw $e;
322
		} 
323
		
324
		return json_decode($res->getBody());
325
	}
326
	
327 1
	private function requestClient()
328
	{
329 1
		$consumer_key = config("{$this->config}.key");
330 1
		$consumer_secret = config("{$this->config}.secret");
331 1
		$token = config("{$this->config}.token");
332 1
		$secret = config("{$this->config}.token_secret");
333
334 1
		$stack = HandlerStack::create();
335 1
		$auth = new Oauth1([
336 1
			'consumer_key'	=> $consumer_key,
337 1
			'consumer_secret' => $consumer_secret,
338 1
			'token'		   => $token,
339 1
			'token_secret'	=> $secret,
340 1
			'signature_method'=> Oauth1::SIGNATURE_METHOD_HMAC,
341
		]);
342 1
		$stack->push($auth);
343
344 1
		$client = new Client([
345 1
			'handler' => $stack,
346
		]);
347
		
348 1
		return $client;
349
	}
350
351 1
	private function requestV1($url, $method, $payload = false)
352
	{
353 1
		$client = $this->requestClient();
354
355
		$args = [
356 1
			'auth' => 'oauth',
357
			'headers' => [
358
				'content-type' => 'application/json',
359
			],
360
		];
361
362 1
		if ($payload !== false) {
363
			$args['body'] = json_encode($payload);
364
		}
365
366
		try {
367 1
			$res = $client->request($method, $url, $args);
368
369 1
			$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 1
		return $response;
385
	}
386
}
387