ApiRequest::_requestRaw()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 19
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 13
c 1
b 0
f 0
nc 2
nop 4
dl 0
loc 19
rs 9.8333
1
<?php
2
3
namespace bSecure;
4
use bSecure\Helpers\Constant;
5
6
/**
7
 * Class ApiRequest.
8
 */
9
class ApiRequest
10
{
11
12
    /**
13
     * @var string
14
     */
15
    private $_apiBase;
16
17
    /**
18
     * @var HttpClient\ClientInterface
19
     */
20
    private static $_httpClient;
21
22
    /**
23
     * ApiRequest constructor.
24
     *
25
     * @param null|string $apiBase
26
     */
27
    public function __construct( $apiBase = null)
28
    {
29
        if (!$apiBase) {
30
            $apiBase = bSecure::$apiBase;
31
        }
32
        $this->_apiBase = $apiBase;
33
    }
34
35
    /**
36
     * @param string $method
37
     * @param string $url
38
     * @param null|array $params
39
     * @param null|array $headers
40
     *
41
     * @throws Exception\ApiErrorException
42
     *
43
     * @return array tuple containing (ApiReponse, API key)
44
     */
45
    public function request($method, $url, $params = null, $authKey = Constant::NO)
46
    {
47
        $params = $params ?: [];
48
        list($rcode, $rbody, $rheaders) =
49
          $this->_requestRaw($method, $url, $params, $authKey);
50
        list($message, $exception, $rbody) = $this->_interpretResponse( $rcode,$rbody, $rheaders);
51
52
        $resp = new ApiResponse($rbody, $rcode, $message, $exception);
53
        return [$resp];
54
    }
55
56
    /**
57
     * @static
58
     *
59
     * @param string $apiKey
60
     *
61
     * @return array
62
     */
63
    private static function _defaultHeaders($authKey = false)
64
    {
65
        $authHeader = [];
66
        $defaultHeaders = [];
67
68
        if($authKey)
69
        {
70
            $authToken = bSecure::getAuthToken();
71
            if(gettype($authToken) == "string")
72
            {
73
                $authHeader = ['Authorization' => 'Bearer ' .$authToken];
74
            }else if(gettype($authToken) == "object"){
75
                $authHeader = [];
76
            }
77
        }
78
        $headers = array_merge($defaultHeaders,$authHeader);
79
        return $headers;
80
    }
81
82
    /**
83
     * @param string $method
84
     * @param string $url
85
     * @param array $params
86
     * @param array $headers
87
     *
88
     * @throws Exception\AuthenticationException
89
     * @throws Exception\ApiConnectionException
90
     *
91
     * @return array
92
     */
93
    private function _requestRaw($method, $url, $params, $authKey)
94
    {
95
        $absUrl = $this->_apiBase . $url;
96
        $defaultHeaders = $this->_defaultHeaders($authKey);
97
98
        $combinedHeaders = $defaultHeaders;
99
        $rawHeaders = [];
100
101
        foreach ($combinedHeaders as $header => $value) {
102
            $rawHeaders[] = $header . ': ' . $value;
103
        }
104
        list($rbody, $rcode, $rheaders) = $this->httpClient()->request(
105
          $method,
106
          $absUrl,
107
          $rawHeaders,
108
          $params,
109
          false
0 ignored issues
show
Unused Code introduced by
The call to bSecure\HttpClient\ClientInterface::request() has too many arguments starting with false. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

109
        list($rbody, $rcode, $rheaders) = $this->httpClient()->/** @scrutinizer ignore-call */ request(

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
110
        );
111
        return [$rbody, $rcode, $rheaders];
112
    }
113
114
    /**
115
     * @param string $rbody
116
     * @param int $rcode
117
     * @param array $rheaders
118
     *
119
     * @throws Exception\UnexpectedValueException
120
     * @throws Exception\ApiErrorException
121
     *
122
     * @return array
123
     */
124
    private function _interpretResponse( $rcode,$rbody, $rheaders)
0 ignored issues
show
Unused Code introduced by
The parameter $rheaders is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

124
    private function _interpretResponse( $rcode,$rbody, /** @scrutinizer ignore-unused */ $rheaders)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
125
    {
126
        $resp = \json_decode($rbody, true);
127
        $jsonError = \json_last_error();
128
129
        if (null === $resp && \JSON_ERROR_NONE !== $jsonError) {
130
            $msg = "Invalid response body from API: {$rbody} "
131
              . "(HTTP response code was {$rcode}, json_last_error() was {$jsonError})";
132
            throw new Exception\UnexpectedValueException($msg, $rcode);
133
        }
134
        $message = $resp['message'];
135
        $exception = $resp['exception'];
136
        $rbody = $resp['body'];
137
138
        return [$message, $exception, $rbody];
139
    }
140
141
    /**
142
     * @param string $rbody a JSON string
143
     * @param int $rcode
144
     * @param array $rheaders
145
     * @param array $resp
146
     *
147
     * @throws Exception\UnexpectedValueException
148
     * @throws Exception\ApiErrorException
149
     */
150
    public function handleErrorResponse($rbody, $rcode, $rheaders, $resp)
151
    {
152
        $errorData = $resp['message'];
153
        $error = null;
154
        if (\is_array($errorData) && $errorData != []) {
155
            $error = self::_specificAPIError($resp,$rheaders,$rcode);
156
        }else{
157
            if (!\is_array($resp) || !isset($resp['error'])) {
0 ignored issues
show
introduced by
The condition is_array($resp) is always true.
Loading history...
158
                $msg = "Invalid response object from API: {$rbody} "
159
                  . "(HTTP response code was {$rcode})";
160
161
                throw new Exception\UnexpectedValueException($msg);
162
            }
163
        }
164
165
        throw $error;
166
    }
167
    /**
168
     * @static
169
     *
170
     * @param string $rbody
171
     * @param int    $rcode
172
     * @param array  $rheaders
173
     * @param array  $resp
174
     * @param array  $errorData
175
     *
176
     * @return Exception\ApiErrorException
177
     */
178
    private static function _specificAPIError($errorData,$rheaders, $code)
0 ignored issues
show
Unused Code introduced by
The parameter $code is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

178
    private static function _specificAPIError($errorData,$rheaders, /** @scrutinizer ignore-unused */ $code)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
179
    {
180
        $msg = isset($errorData['message']) ? $errorData['message'] : null;
181
        $body = isset($errorData['body']) ? $errorData['body'] : null;
182
        $code = isset($errorData['status']) ? $errorData['status'] : null;
183
        $exception = isset($errorData['exception']) ? $errorData['exception'] : null;
184
185
        return Exception\InvalidRequestException::factory($msg, $code, $body, $exception, $rheaders, $code);
186
    }
187
    /**
188
     * @static
189
     *
190
     * @param HttpClient\ClientInterface $client
191
     */
192
    public static function setHttpClient($client)
193
    {
194
        self::$_httpClient = $client;
195
    }
196
197
198
    /**
199
     * @return HttpClient\ClientInterface
200
     */
201
    private function httpClient()
202
    {
203
        if (!self::$_httpClient) {
204
            self::$_httpClient = HttpClient\CurlClient::instance();
205
        }
206
207
        return self::$_httpClient;
208
    }
209
}