Passed
Push — master ( 92de42...ada49a )
by Jacques
02:29
created

Client::clientError()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 10
Ratio 100 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 10
loc 10
ccs 5
cts 5
cp 1
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php declare(strict_types=1);
2
/**
3
 * SmartCall Restful API (v3) HTTP Client.
4
 *
5
 * PLEASE NOTE: The interface is very fluid while the intial integration
6
 * is taking place.  It will be refactored in the near future.
7
 *
8
 * @author    Jacques Marneweck <[email protected]>
9
 * @copyright 2017-2019 Jacques Marneweck.  All rights strictly reserved.
10
 * @license   MIT
11
 */
12
13
namespace Jacques\Smartcall\HttpClient;
14
15
use Jacques\Smartcall\HttpClient\Traits\SmartLoad;
16
use Jacques\Smartcall\HttpClient\Traits\SmartRica;
17
18
class Client extends \GuzzleHttp\Client
19
{
20
    use SmartLoad;
21
    use SmartRica;
22
23
    /**
24
     * @const string Version number
25
     */
26
    const VERSION = '0.0.1';
27
28
    /**
29
     * Defaults to expecting that Apache Tomcat runs on port 8080 on localhost
30
     * (127.0.0.1).
31
     *
32
     * @var array
33
     */
34
    protected $options = [
35
        'scheme'   => 'https',
36
        'hostname' => 'localhost',
37
        'port'     => '8080',
38
        'token'    => null,
39
        'username' => null,
40
        'password' => null,
41
    ];
42
43
    /**
44
     * @param array $options
45
     */
46 61
    public function __construct($options = [])
47
    {
48
        /*
49
         * Allow on instantiation to overwrite the defaults
50
         */
51 61
        $this->options = array_merge(
52 61
            $this->options,
53 61
            $options
54
        );
55
        $config = [
56 61
            'base_uri' => sprintf(
57 61
                '%s://%s:%s/',
58 61
                $this->options['scheme'],
59 61
                $this->options['hostname'],
60 61
                $this->options['port']
61
            ),
62
            'verify'  => false,
63
            'headers' => [
64 61
                'User-Agent' => 'SmartcallRestfulAPIClient-PHP/'.self::VERSION.' '.\GuzzleHttp\default_user_agent(),
65
            ],
66
        ];
67 61
        parent::__construct($config);
68 61
    }
69
70
    /**
71
     * Set the bearer token.
72
     *
73
     * @param string $token Bearer Token from Auth request
74
     *
75
     * @return void
76
     */
77 45
    public function setBearerToken($token): void
78
    {
79 45
        $this->options['token'] = $token;
80 45
    }
81
82
    /**
83
     * Set the password for basic authentication.
84
     *
85
     * @param string $password Password for use with basic authentication
86
     *
87
     * @return void
88
     */
89 5
    public function setPassword($password): void
90
    {
91 5
        $this->options['password'] = $password;
92 5
    }
93
94
    /**
95
     * Set the username for basic authentication.
96
     *
97
     * @param string $username Username for use with basic authentication
98
     *
99
     * @return void
100
     */
101 5
    public function setUsername($username): void
102
    {
103 5
        $this->options['username'] = $username;
104 5
    }
105
106
    /**
107
     * Authenticate and get Bearer token from SmartCall.
108
     *
109
     * @throws Exception
110
     *
111
     * @return array
112
     */
113 4 View Code Duplication
    public function auth()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
114
    {
115
        try {
116 4
            $response = $this->post(
117 4
                '/webservice/auth',
118
                [
119
                    'headers' => [
120 4
                        'Authorization' => $this->bearerOrBasic(),
121
                    ],
122
                ]
123
            );
124
125
            return [
126 1
                'status'    => 'ok',
127 1
                'http_code' => $response->getStatusCode(),
128 1
                'body'      => (string) $response->getBody(),
129
            ];
130 3
        } catch (\GuzzleHttp\Exception\ClientException $e) {
131 3
            return $this->clientError($e);
132
        } catch (\GuzzleHttp\Exception\ServerException $e) {
133
            return $this->parseError($e);
134
        }
135
    }
136
137
    /**
138
     * Authenticate and invalidates all the user allocated tokens.
139
     *
140
     * @throws Exception
141
     *
142
     * @return array
143
     */
144 2 View Code Duplication
    public function authDelete()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
145
    {
146
        try {
147 2
            $response = $this->delete(
148 2
                '/webservice/auth',
149
                [
150
                    'headers' => [
151 2
                        'Authorization' => $this->bearerOrBasic(),
152
                    ],
153
                ]
154
            );
155
156
            return [
157 1
                'status'    => 'ok',
158 1
                'http_code' => $response->getStatusCode(),
159 1
                'body'      => (string) $response->getBody(),
160
            ];
161 1
        } catch (\GuzzleHttp\Exception\ClientException $e) {
162 1
            return $this->clientError($e);
163
        } catch (\GuzzleHttp\Exception\ServerException $e) {
164
            return $this->parseError($e);
165
        }
166
    }
167
168
    /**
169
     * Authenticate and invalidates all the user allocated tokens.
170
     *
171
     * @throws Exception
172
     *
173
     * @return array
174
     */
175 3 View Code Duplication
    public function authFlush()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
176
    {
177
        try {
178 3
            $response = $this->delete(
179 3
                '/webservice/auth/token',
180
                [
181
                    'headers' => [
182 3
                        'Authorization' => $this->bearerOrBasic(),
183
                    ],
184
                ]
185
            );
186
187
            return [
188 2
                'status'    => 'ok',
189 2
                'http_code' => $response->getStatusCode(),
190 2
                'body'      => (string) $response->getBody(),
191
            ];
192 1
        } catch (\GuzzleHttp\Exception\ClientException $e) {
193 1
            return $this->clientError($e);
194
        } catch (\GuzzleHttp\Exception\ServerException $e) {
195
            return $this->parseError($e);
196
        }
197
    }
198
199
    /**
200
     * Authenticate and gets the number of available session tokens.
201
     *
202
     * @throws Exception
203
     *
204
     * @return array
205
     */
206 3 View Code Duplication
    public function authToken()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
207
    {
208
        try {
209 3
            $response = $this->get(
210 3
                '/webservice/auth/token',
211
                [
212
                    'headers' => [
213 3
                        'Authorization' => $this->bearerOrBasic(),
214
                    ],
215
                ]
216
            );
217
218
            return [
219 1
                'status'    => 'ok',
220 1
                'http_code' => $response->getStatusCode(),
221 1
                'body'      => (string) $response->getBody(),
222
            ];
223 2
        } catch (\GuzzleHttp\Exception\ClientException $e) {
224 2
            return $this->clientError($e);
225
        } catch (\GuzzleHttp\Exception\ServerException $e) {
226
            return $this->parseError($e);
227
        }
228
    }
229
230
    /**
231
     * Gets the current connection status to the various mobile networks.
232
     *
233
     * @throws Exception
234
     *
235
     * @return array
236
     */
237 3 View Code Duplication
    public function health()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
238
    {
239
        try {
240 3
            $response = $this->get(
241 3
                '/webservice/utilities/health',
242
                [
243
                    'headers' => [
244 3
                        'Authorization' => $this->bearerOrBasic(),
245
                    ],
246
                ]
247
            );
248
249
            return [
250 1
                'status'    => 'ok',
251 1
                'http_code' => $response->getStatusCode(),
252 1
                'body'      => (string) $response->getBody(),
253
            ];
254 2
        } catch (\GuzzleHttp\Exception\ClientException $e) {
255 2
            return $this->clientError($e);
256
        } catch (\GuzzleHttp\Exception\ServerException $e) {
257
            return $this->parseError($e);
258
        }
259
    }
260
261
    /**
262
     * Gets the mobile network on which the SIM is connected.
263
     *
264
     * @param string $msisdn
265
     *
266
     * @throws Exception
267
     *
268
     * @return array
269
     */
270 4 View Code Duplication
    public function simnetwork($msisdn)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
271
    {
272
        try {
273 4
            $response = $this->get(
274 4
                sprintf(
275 4
                    '/webservice/utilities/simnetwork/%d',
276 4
                    $msisdn
277
                ),
278
                [
279
                    'headers' => [
280 4
                        'Authorization' => $this->bearerOrBasic(),
281
                    ],
282
                ]
283
            );
284
285
            return [
286 2
                'status'    => 'ok',
287 2
                'http_code' => $response->getStatusCode(),
288 2
                'body'      => (string) $response->getBody(),
289
            ];
290 2
        } catch (\GuzzleHttp\Exception\ClientException $e) {
291 2
            return $this->clientError($e);
292
        } catch (\GuzzleHttp\Exception\ServerException $e) {
293
            return $this->parseError($e);
294
        }
295
    }
296
297
    /**
298
     * Test SmartCall is responding.
299
     *
300
     * @throws Exception
301
     *
302
     * @return array
303
     */
304 1
    public function ping()
305
    {
306
        try {
307 1
            $response = $this->get(
308 1
                '/webservice/test/ping'
309
            );
310
311
            return [
312 1
                'status'    => 'ok',
313 1
                'http_code' => $response->getStatusCode(),
314 1
                'body'      => (string) $response->getBody(),
315
            ];
316
        } catch (\GuzzleHttp\Exception\ClientException $e) {
317
            return $this->clientError($e);
318
        } catch (\GuzzleHttp\Exception\ServerException $e) {
319
            return $this->parseError($e);
320
        }
321
    }
322
323
    /**
324
     * Parse the java exception that we receive from Smartcall's Tomcat's.
325
     *
326
     * @param \GuzzleHttp\Exception\ClientException $exception
327
     *
328
     * @return array
329
     */
330 29 View Code Duplication
    private function clientError(\GuzzleHttp\Exception\ClientException $exception): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
331
    {
332 29
        $body = (string) $exception->getResponse()->getBody();
333
334
        return [
335 29
            'status'    => 'error',
336 29
            'http_code' => $exception->getResponse()->getStatusCode(),
337 29
            'body'      => json_decode($body),
338
        ];
339
    }
340
341
    /**
342
     * Parse the java exception that we receive from Smartcall's Tomcat's.
343
     *
344
     * @param \GuzzleHttp\Exception\ServerException $exception
345
     *
346
     * @return array
347
     */
348 View Code Duplication
    private function parseError(\GuzzleHttp\Exception\ServerException $exception): array
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
349
    {
350
        $body = (string) $exception->getResponse()->getBody();
351
        preg_match('/<p><b>(JBWEB\d{6}): type<\/b> (JBWEB\d{6}): Exception report<\/p><p><b>(JBWEB\d{6}): message<\/b> <u>(.*[^<\/u>])<\/u><\/p><p><b>(JBWEB\d{6}): description<\/b> <u>(.+[^<\/u>])<\/u><\/p>/ims', $body, $matches);
352
353
        return [
354
            'status'    => 'error',
355
            'http_code' => $exception->getResponse()->getStatusCode(),
356
            'body'      => $matches['6'],
357
        ];
358
    }
359
360
    /**
361
     * Use basic authentication header content if bearer token  is not set.
362
     *
363
     * @return string
364
     */
365 56
    private function bearerOrBasic(): string
366
    {
367
        /**
368
         * Get the function calling this method.
369
         */
370 56
        $caller = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2)[1]['function'];
371
372
        if (
373 56
            !in_array(
374 56
                $caller,
375
                [
376 56
                    'auth',
377
                ]
378
            )
379
        ) {
380 52
            return sprintf(
381 52
                'Bearer %s',
382 52
                $this->options['token']
383
            );
384
        }
385
386 4
        return sprintf(
387 4
            'Basic %s',
388 4
            base64_encode(
389 4
                sprintf(
390 4
                    '%s:%s',
391 4
                    $this->options['username'],
392 4
                    $this->options['password']
393
                )
394
            )
395
        );
396
    }
397
}
398