Completed
Push — master ( 23d8ab...909a9d )
by Kanto
23s queued 11s
created

HttpClient::communicate()   C

Complexity

Conditions 12
Paths 32

Size

Total Lines 47
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
cc 12
eloc 33
c 3
b 0
f 0
nc 32
nop 5
dl 0
loc 47
rs 6.9666

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Kore : Simple And Minimal Framework
4
 *
5
 */
6
7
namespace Kore;
8
9
use Kore\Log;
10
11
/**
12
 * HttpClient class
13
 *
14
 */
15
class HttpClient
16
{
17
    /**
18
     * GET Communication
19
     *
20
     * @param string $url request url
21
     * @param array<mixed> $params request parameters
22
     * @param array<mixed> $headers request headers
23
     * @param string|null $userpwd user name and password
24
     * @return HttpResponse|false \Kore\HttpResponse
25
     * @see \Kore\HttpResponse
26
     */
27
    public function get($url, $params = [], $headers = [], $userpwd = null)
28
    {
29
        return $this->communicate('GET', $url, $params, $headers, $userpwd);
30
    }
31
32
    /**
33
     * POST Communication
34
     *
35
     * @param string $url request url
36
     * @param array<mixed> $params request parameters
37
     * @param array<mixed> $headers request headers
38
     * @param string|null $userpwd user name and password
39
     * @return HttpResponse|false \Kore\HttpResponse
40
     * @see \Kore\HttpResponse
41
     */
42
    public function post($url, $params = [], $headers = [], $userpwd = null)
43
    {
44
        return $this->communicate('POST', $url, $params, $headers, $userpwd);
45
    }
46
47
    /**
48
     * PUT Communication
49
     *
50
     * @param string $url request url
51
     * @param array<mixed> $params request parameters
52
     * @param array<mixed> $headers request headers
53
     * @param string|null $userpwd user name and password
54
     * @return HttpResponse|false
55
     * @see \Kore\HttpResponse
56
     */
57
    public function put($url, $params = [], $headers = [], $userpwd = null)
58
    {
59
        return $this->communicate('PUT', $url, $params, $headers, $userpwd);
60
    }
61
62
    /**
63
     * PATCH Communication
64
     *
65
     * @param string $url request url
66
     * @param array<mixed> $params request parameters
67
     * @param array<mixed> $headers request headers
68
     * @param string|null $userpwd user name and password
69
     * @return HttpResponse|false \Kore\HttpResponse
70
     * @see \Kore\HttpResponse
71
     */
72
    public function patch($url, $params = [], $headers = [], $userpwd = null)
73
    {
74
        return $this->communicate('PATCH', $url, $params, $headers, $userpwd);
75
    }
76
77
    /**
78
     * DELETE Communication
79
     *
80
     * @param string $url request url
81
     * @param array<mixed> $params request parameters
82
     * @param array<mixed> $headers request headers
83
     * @param string|null $userpwd user name and password
84
     * @return HttpResponse|false \Kore\HttpResponse
85
     * @see \Kore\HttpResponse
86
     */
87
    public function delete($url, $params = [], $headers = [], $userpwd = null)
88
    {
89
        return $this->communicate('DELETE', $url, $params, $headers, $userpwd);
90
    }
91
92
    /**
93
     * Communication Processing
94
     *
95
     * @param string $method http method
96
     * @param string $url request url
97
     * @param array<mixed> $params request parameters
98
     * @param array<mixed> $headers request headers
99
     * @param string|null $userpwd user name and password
100
     * @return HttpResponse|false \Kore\HttpResponse
101
     * @see \Kore\HttpResponse
102
     */
103
    protected function communicate($method, $url, $params = [], $headers = [], $userpwd = null)
104
    {
105
        $headers = $this->buildHeader($headers);
106
        
107
        $curl = curl_init();
108
109
        curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
110
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
111
        curl_setopt($curl, CURLOPT_HEADER, true);
112
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
113
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
114
        if ($method === 'GET') {
115
            curl_setopt($curl, CURLOPT_URL, $url . (strpos($url, '?') === false ? '?' : '&') . http_build_query($params));
116
        } elseif ($method === 'POST' || $method === 'PUT' || $method === 'PATCH' || $method === 'DELETE') {
117
            curl_setopt($curl, CURLOPT_URL, $url);
118
            $json_headers = preg_grep("/^Content-Type: application\/json/i", $headers);
119
            if ($json_headers !== false && count($json_headers) > 0) {
120
                $data = json_encode($params);
121
            } else {
122
                $data = http_build_query($params);
123
            }
124
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
125
        }
126
        if (!empty($headers)) {
127
            curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
128
        }
129
        if ($userpwd !== null) {
130
            curl_setopt($curl, CURLOPT_USERPWD, $userpwd);
131
        }
132
133
        $response = curl_exec($curl);
134
        $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
135
        $header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE);
136
        $total_time = curl_getinfo($curl, CURLINFO_TOTAL_TIME);
137
138
        curl_close($curl);
139
140
        Log::debug(sprintf('[%s][%s][%ssec]', $url, $http_code, $total_time));
141
        if (!$response) {
142
            Log::info('Acquisition failed');
143
            return false;
144
        }
145
        /** @phpstan-ignore-next-line */
146
        $header = substr($response, 0, $header_size);
147
        /** @phpstan-ignore-next-line */
148
        $body = substr($response, $header_size);
149
        return new HttpResponse($http_code, $header, $body);
150
    }
151
152
    /**
153
     * Build headers
154
     *
155
     * Build the associative array headers into a curl-friendly format.
156
     * @param array<mixed> $headers headers
157
     * @return array<string> built headers
158
     */
159
    protected function buildHeader($headers)
160
    {
161
        $h = array();
162
        foreach ($headers as $key => $value) {
163
            if (is_string($key)) {
164
                $h[] = "$key: $value";
165
            } else {
166
                $h[] = $value;
167
            }
168
        }
169
        return $h;
170
    }
171
}
172
173
/**
174
 * HttpResponse class
175
 *
176
 */
177
class HttpResponse
178
{
179
    /**
180
     * __construct method
181
     *
182
     * @param int $httpCode http status code
183
     * @param string $header response headers
184
     * @param string $body response body
185
     * @return void
186
     */
187
    public function __construct($httpCode, $header, $body)
188
    {
189
        $this->httpCode = $httpCode;
190
        $this->header = $header;
191
        $this->body = $body;
192
    }
193
194
    /**
195
     * http status code
196
     *
197
     * @var int
198
     */
199
    private $httpCode;
200
    /**
201
     * response headers
202
     *
203
     * @var string
204
     */
205
    private $header;
206
    /**
207
     * response body
208
     *
209
     * @var string
210
     */
211
    private $body;
212
213
    /**
214
     * Get the http status code
215
     *
216
     * @return int http status code
217
     */
218
    public function getHttpCode()
219
    {
220
        return $this->httpCode;
221
    }
222
223
    /**
224
     * Get the response headers
225
     *
226
     * @return string response headers
227
     */
228
    public function getHeader()
229
    {
230
        return $this->header;
231
    }
232
233
    /**
234
     * Get the header value by specifying the header name
235
     *
236
     * @param string $key header name
237
     * @return string|null header value
238
     */
239
    public function getHeaderLine($key)
240
    {
241
        preg_match("/$key: (\S*)/i", $this->getHeader(), $matches);
242
        if (!isset($matches[1])) {
243
            return null;
244
        }
245
        return $matches[1];
246
    }
247
248
    /**
249
     * Get the response body
250
     *
251
     * @return string response body
252
     */
253
    public function getBody()
254
    {
255
        return $this->body;
256
    }
257
    
258
    /**
259
     * Get the response body in json format
260
     *
261
     * @return array<mixed> response body
262
     */
263
    public function getJsonBody()
264
    {
265
        return json_decode($this->getBody(), true);
266
    }
267
}
268