Passed
Push — master ( 44ef80...2a18fa )
by Ehsan
03:32
created

ApiClient::setArrayUtility()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Botonomous\client;
4
5
use Botonomous\Config;
6
use Botonomous\ImChannel;
7
use Botonomous\Team;
8
use Botonomous\utility\ArrayUtility;
9
use /* @noinspection PhpUndefinedClassInspection */
10
    GuzzleHttp\Client;
11
use /* @noinspection PhpUndefinedClassInspection */
12
    GuzzleHttp\Psr7\Request;
13
14
/**
15
 * Class ApiClient.
16
 */
17
class ApiClient
18
{
19
    const BASE_URL = 'https://slack.com/api/';
20
21
    private $arguments = [
22
        'rtm.start' => [
23
            'required' => [
24
                'token',
25
            ],
26
            'optional' => [
27
                'simple_latest',
28
                'no_unreads',
29
                'mpim_aware',
30
            ],
31
        ],
32
        'chat.postMessage' => [
33
            'required' => [
34
                'token',
35
                'channel',
36
                'text',
37
            ],
38
            'optional' => [
39
                'parse',
40
                'link_names',
41
                'attachments',
42
                'unfurl_links',
43
                'unfurl_media',
44
                'username',
45
                'as_user',
46
                'icon_url',
47
                'icon_emoji',
48
            ],
49
        ],
50
        'oauth.access' => [
51
            'required' => [
52
                'client_id',
53
                'client_secret',
54
                'code',
55
            ],
56
            'optional' => [
57
                'redirect_uri',
58
            ],
59
        ],
60
        'team.info' => [
61
            'required' => [
62
                'token',
63
            ],
64
        ],
65
        'im.list' => [
66
            'required' => [
67
                'token',
68
            ],
69
        ],
70
        'users.list' => [
71
            'required' => [
72
                'token',
73
            ],
74
            'optional' => [
75
                'presence',
76
            ],
77
        ],
78
        'users.info' => [
79
            'required' => [
80
                'token',
81
                'user',
82
            ],
83
        ],
84
    ];
85
86
    private $client;
87
    private $token;
88
    private $arrayUtility;
89
90
    /**
91
     * ApiClient constructor.
92
     *
93
     * @param null $token
94
     */
95 43
    public function __construct($token = null)
96
    {
97 43
        $this->setToken($token);
98 43
    }
99
100
    /**
101
     * API CURL Call with post method.
102
     *
103
     * @param string $method
104
     * @param array  $arguments
105
     *
106
     * @throws \Exception
107
     *
108
     * @return mixed
109
     */
110 33
    public function apiCall($method, array $arguments = [])
111
    {
112 33
        $arguments = array_merge($arguments, $this->getArgs());
113
114
        // check the required arguments are provided
115
        try {
116 33
            $this->validateRequiredArguments($method, $arguments);
117 3
        } catch (\Exception $e) {
118 3
            throw new \Exception('Missing required argument(s): '.$e->getMessage());
119
        }
120
121
        // filter unwanted arguments
122 30
        $arguments = $this->filterArguments($method, $arguments);
123
124
        try {
125
            /** @noinspection PhpUndefinedClassInspection */
126 30
            $request = new Request(
127 30
                'POST',
128 30
                self::BASE_URL.$method,
129 30
                ['Content-Type' => 'application/x-www-form-urlencoded'],
130
                http_build_query($arguments)
131
            );
132
133 30
            $response = $this->getClient()->send($request);
134 2
        } catch (\Exception $e) {
135 2
            throw new \Exception('Failed to send data to the Slack API: '.$e->getMessage());
136
        }
137
138
        try {
139 28
            return $this->processResponse($response);
140 1
        } catch (\Exception $e) {
141 1
            throw $e;
142
        }
143
    }
144
145
    /**
146
     * @param $response
147
     *
148
     * @throws \Exception
149
     *
150
     * @return mixed
151
     */
152 28
    private function processResponse($response)
153
    {
154 28
        $response = json_decode($response->getBody()->getContents(), true);
155
156 28
        if (!is_array($response)) {
157 1
            throw new \Exception('Failed to process response from the Slack API');
158
        }
159
160 27
        return $response;
161
    }
162
163
    /**
164
     * @throws \Exception
165
     *
166
     * @return array
167
     */
168 34
    public function getArgs()
169
    {
170 34
        $config = new Config();
171
172
        return [
173 34
            'token'    => $this->getToken(),
174 34
            'username' => $config->get('botUsername'),
175 34
            'as_user'  => $config->get('asUser'),
176 34
            'icon_url' => $config->get('iconURL'),
177
        ];
178
    }
179
180
    /**
181
     * @param $arguments
182
     *
183
     * @return mixed
184
     */
185 2
    public function chatPostMessage($arguments)
186
    {
187 2
        return $this->apiCall('chat.postMessage', $arguments);
188
    }
189
190
    /**
191
     * @param $arguments
192
     *
193
     * @throws \Exception
194
     *
195
     * @return mixed
196
     */
197 1
    public function rtmStart($arguments)
198
    {
199 1
        return $this->apiCall('rtm.start', $arguments);
200
    }
201
202
    /**
203
     * @throws \Exception
204
     *
205
     * @return array
206
     * @return Team
207
     */
208 4
    public function teamInfo()
209
    {
210 4
        $teamInfo = $this->apiCall('team.info');
211
212 4
        if (!isset($teamInfo['team'])) {
213 2
            return [];
214
        }
215
216 2
        return $teamInfo['team'];
217
    }
218
219
    /**
220
     * @return null|\Botonomous\AbstractBaseSlack
221
     */
222 2
    public function teamInfoAsObject()
223
    {
224 2
        $teamInfo = $this->teamInfo();
225
226 2
        if (empty($teamInfo)) {
227
            /* @noinspection PhpInconsistentReturnPointsInspection */
228 1
            return;
229
        }
230
231
        // return as object
232 1
        return (new Team())->load($teamInfo);
233
    }
234
235
    /**
236
     * List all the Slack users in the team.
237
     *
238
     * @return array
239
     */
240 2
    public function usersList()
241
    {
242 2
        $result = $this->apiCall('users.list');
243
244 2
        if (!isset($result['members'])) {
245 1
            return [];
246
        }
247
248 1
        return $result['members'];
249
    }
250
251
    /**
252
     * Return a user by Slack user id.
253
     *
254
     * @param $arguments
255
     *
256
     * @throws \Exception
257
     *
258
     * @return mixed
259
     */
260 10
    public function userInfo($arguments)
261
    {
262 10
        $result = $this->apiCall('users.info', $arguments);
263
264 10
        if (!isset($result['user'])) {
265
            /* @noinspection PhpInconsistentReturnPointsInspection */
266 4
            return;
267
        }
268
269 6
        return $result['user'];
270
    }
271
272
    /**
273
     * @throws \Exception
274
     *
275
     * @return mixed
276
     */
277 1
    public function test()
278
    {
279 1
        return $this->apiCall('api.test');
280
    }
281
282
    /**
283
     * @throws \Exception
284
     *
285
     * @return array
286
     */
287 5
    public function imList()
288
    {
289 5
        $result = $this->apiCall('im.list');
290
291 5
        if (!isset($result['ims'])) {
292 2
            return [];
293
        }
294
295 4
        return $result['ims'];
296
    }
297
298
    /**
299
     * @return array
300
     */
301 4
    public function imListAsObject()
302
    {
303 4
        $imChannels = $this->imList();
304
305 4
        $imChannelObjects = [];
306 4
        if (empty($imChannels)) {
307 1
            return $imChannelObjects;
308
        }
309
310 3
        foreach ($imChannels as $imChannel) {
311 3
            $imChannelObjects[$imChannel['id']] = (new ImChannel())->load($imChannel);
312
        }
313
314 3
        return $imChannelObjects;
315
    }
316
317
    /**
318
     * @param $arguments
319
     *
320
     * @throws \Exception
321
     *
322
     * @return mixed
323
     */
324 5
    public function oauthAccess($arguments)
325
    {
326 5
        return $this->apiCall('oauth.access', $arguments);
327
    }
328
329
    /** @noinspection PhpUndefinedClassInspection
330
     * @param Client $client
331
     */
332 33
    public function setClient(Client $client)
333
    {
334 33
        $this->client = $client;
335 33
    }
336
337
    /** @noinspection PhpUndefinedClassInspection
338
     * @return Client|null
339
     */
340 30
    public function getClient()
341
    {
342 30
        if (!isset($this->client)) {
343
            /* @noinspection PhpUndefinedClassInspection */
344 8
            $this->setClient(new Client());
345
        }
346
347 30
        return $this->client;
348
    }
349
350
    /**
351
     * @param $method
352
     * @param $arguments
353
     *
354
     * @throws \Exception
355
     *
356
     * @return bool
357
     */
358 33
    private function validateRequiredArguments($method, $arguments)
359
    {
360 33
        $validArguments = $this->getArguments($method);
361
362 33
        if (empty($validArguments['required'])) {
363 3
            return true;
364
        }
365
366 30
        foreach ($validArguments['required'] as $argument) {
367 30
            if ($this->getArrayUtility()->arrayKeyValueExists($argument, $arguments) !== true) {
368 30
                throw new \Exception("{$argument} must be provided for {$method}");
369
            }
370
        }
371
372 27
        return true;
373
    }
374
375
    /**
376
     * @param null $method
377
     *
378
     * @throws \Exception
379
     *
380
     * @return mixed
381
     */
382 35
    public function getArguments($method = null)
383
    {
384 35
        if ($method !== null) {
385 34
            if (!isset($this->arguments[$method])) {
386
                /* @noinspection PhpInconsistentReturnPointsInspection */
387 3
                return;
388
            }
389
390 31
            return $this->arguments[$method];
391
        }
392
393 1
        return $this->arguments;
394
    }
395
396
    /**
397
     * @param array $arguments
398
     */
399 1
    public function setArguments(array $arguments)
400
    {
401 1
        $this->arguments = $arguments;
402 1
    }
403
404
    /**
405
     * @param       $method
406
     * @param array $arguments
407
     *
408
     * @return array
409
     */
410 31
    public function filterArguments($method, array $arguments)
411
    {
412 31
        $validArguments = $this->getArguments($method);
413
414 31
        if (empty($validArguments)) {
415 3
            return $arguments;
416
        }
417
418 28
        if (!isset($validArguments['optional'])) {
419 19
            $validArguments['optional'] = [];
420
        }
421
422 28
        $extractedArguments = array_merge($validArguments['required'], $validArguments['optional']);
423
424 28
        return (new ArrayUtility())->filterArray($arguments, $extractedArguments);
425
    }
426
427
    /**
428
     * @return string
429
     */
430 34
    public function getToken()
431
    {
432
        // fall back to config
433 34
        if (empty($this->token)) {
434 34
            $this->setToken((new Config())->get('botUserToken'));
435
        }
436
437 34
        return $this->token;
438
    }
439
440
    /**
441
     * @param string $token
442
     */
443 43
    public function setToken($token)
444
    {
445 43
        $this->token = $token;
446 43
    }
447
448
    /**
449
     * @return ArrayUtility
450
     */
451 30
    public function getArrayUtility()
452
    {
453 30
        if (!isset($this->arrayUtility)) {
454 30
            $this->setArrayUtility(new ArrayUtility());
455
        }
456
457 30
        return $this->arrayUtility;
458
    }
459
460
    /**
461
     * @param ArrayUtility $arrayUtility
462
     */
463 30
    public function setArrayUtility(ArrayUtility $arrayUtility)
464
    {
465 30
        $this->arrayUtility = $arrayUtility;
466 30
    }
467
}
468