Passed
Push — master ( ff83e3...5f4a5c )
by Ehsan
03:54
created

ApiClient::getToken()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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