Passed
Push — master ( 56e475...c00592 )
by Ehsan
03:50
created

ApiClient::oauthAccess()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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