Test Failed
Push — master ( 459896...56e475 )
by Ehsan
03:15
created

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