Passed
Push — feature/0.7.0 ( 0c7d59...ae5b22 )
by Ryuichi
78:01 queued 33:04
created

HttpClient.php$0 ➔ http()   F

Complexity

Conditions 19

Size

Total Lines 74

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 19
dl 0
loc 74
rs 2.387
c 0
b 0
f 0

How to fix   Long Method    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
namespace WebStream\Module;
3
4
use WebStream\DI\Injector;
5
6
/**
7
 * HttpClient
8
 * @author Ryuichi TANAKA.
9
 * @since 2010/10/20
10
 * @version 0.7
11
 */
12
class HttpClient
13
{
14
    use Injector;
15
16
    /**
17
     * @var array レスポンスヘッダ
18
     */
19
    private $responseHeader;
20
21
    /**
22
     * @var int レスポンスヘッダ
23
     */
24
    private $status_code;
25
26
    /**
27
     * @var string コンテントタイプ
28
     */
29
    private $content_type;
30
31
    /**
32
     * @var int タイムアウト時間
33
     */
34
    private $timeout;
35
36
    /**
37
     * @var string PROXYホスト名
38
     */
39
    private $proxy_host;
40
41
    /**
42
     * @var int PROXYポート番号
43
     */
44
    private $proxy_port;
45
46
    /**
47
     * @var string Basic認証ID
48
     */
49
    private $basic_auth_id;
50
51
    /**
52
     * @var string Basic認証パスワード
53
     */
54
    private $basic_auth_password;
55
56
    /**
57
     * @var string デフォルトタイムアウト時間
58
     */
59
    const DEFAULT_TIMEOUT = 3;
60
61
    /**
62
     * コンストラクタ
63
     * @param array<string> オプションパラメータ
64
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment オプションパラメータ at position 0 could not be parsed: Unknown type name 'オプションパラメータ' at position 0 in オプションパラメータ.
Loading history...
65
    public function __construct($options = [])
66
    {
67
        $this->timeout             = $this->getOptionParameter($options, "timeout", self::DEFAULT_TIMEOUT);
68
        $this->proxy_host          = $this->getOptionParameter($options, "proxy_host");
69
        $this->proxy_port          = $this->getOptionParameter($options, "proxy_port");
70
        $this->basic_auth_id       = $this->getOptionParameter($options, "basic_auth_id");
71
        $this->basic_auth_password = $this->getOptionParameter($options, "basic_auth_password");
72
        // HttpClientはどのレイヤからも呼び出し可能なので、明示的なロガー注入を必須としない
73
        $this->logger = new class() { public function __call($name, $args) {} };
0 ignored issues
show
Bug Best Practice introduced by
The property logger does not exist on WebStream\Module\HttpClient. Since you implemented __set, consider adding a @property annotation.
Loading history...
74
    }
75
76
    /**
77
     * ステータスコードを返却する
78
     * @return int ステータスコード
79
     */
80
    public function getStatusCode()
81
    {
82
        return $this->status_code;
83
    }
84
85
    /**
86
     * コンテントタイプを返却する
87
     * @return string コンテントタイプ
88
     */
89
    public function getContentType()
90
    {
91
        return $this->content_type;
92
    }
93
94
    /**
95
     * レスポンスヘッダを返却する
96
     * @return array レスポンスヘッダ
97
     */
98
    public function getResponseHeader()
99
    {
100
        return $this->responseHeader;
101
    }
102
103
    /**
104
     * GETリクエストを発行する
105
     * @param string URL
106
     * @param array<mixed> リクエストパラメータ
107
     * @param array リクエストヘッダ
108
     * @return string レスポンス
109
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment リクエストパラメータ at position 0 could not be parsed: Unknown type name 'リクエストパラメータ' at position 0 in リクエストパラメータ.
Loading history...
110
    public function get($url, $params = "", $headers = [])
111
    {
112
        return $this->http($url, $headers, $params, "GET");
113
    }
114
115
    /**
116
     * POSTリクエストを発行する
117
     * @param string URL
118
     * @param array<mixed> リクエストパラメータ
119
     * @param array リクエストヘッダ
120
     * @return string レスポンス
121
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment リクエストパラメータ at position 0 could not be parsed: Unknown type name 'リクエストパラメータ' at position 0 in リクエストパラメータ.
Loading history...
122
    public function post($url, $params, $headers = [])
123
    {
124
        return $this->http($url, $headers, $params, "POST");
125
    }
126
127
    /**
128
     * PUTリクエストを発行する
129
     * @param string URL
130
     * @param array<mixed> リクエストパラメータ
131
     * @param array リクエストヘッダ
132
     * @return string レスポンス
133
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment リクエストパラメータ at position 0 could not be parsed: Unknown type name 'リクエストパラメータ' at position 0 in リクエストパラメータ.
Loading history...
134
    public function put($url, $params, $headers = [])
135
    {
136
        return $this->http($url, $headers, $params, "PUT");
137
    }
138
139
    /**
140
     * PROXY設定をする
141
     * @param array<string> リクエストコンテント
142
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment リクエストコンテント at position 0 could not be parsed: Unknown type name 'リクエストコンテント' at position 0 in リクエストコンテント.
Loading history...
143
    private function proxy(&$request)
144
    {
145
        // 「http://」は「tcp://」に、「https://」は「ssl://」に置換する
146
        $host = $this->proxy_host;
147
        $host = preg_replace('/^http(:\/\/.+)$/', 'tcp${1}', $host);
148
        $host = preg_replace('/^https(:\/\/.+)$/', 'ssl${1}', $host);
149
        $request["proxy"] = $host . ":" . strval($this->proxy_port);
150
        $request["request_fulluri"] = true;
151
    }
152
153
    /**
154
     * Basic認証を設定する
155
     * @param array リクエストヘッダ
156
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment リクエストヘッダ at position 0 could not be parsed: Unknown type name 'リクエストヘッダ' at position 0 in リクエストヘッダ.
Loading history...
157
    private function basicAuth(&$headers)
158
    {
159
        $headers[] = "Authorization: Basic " .
160
            base64_encode($this->basic_auth_id . ":" . $this->basic_auth_password);
161
    }
162
163
    /**
164
     * HTTP通信を実行する
165
     * @param string URL
166
     * @param array リクエストヘッダ
167
     * @param array<string> リクエストパラメータ
168
     * @param string 実行するRESTメソッド
169
     * @return string レスポンス
170
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment リクエストヘッダ at position 0 could not be parsed: Unknown type name 'リクエストヘッダ' at position 0 in リクエストヘッダ.
Loading history...
171
    private function http($url, $headers, $params, $method)
172
    {
173
        if (!empty($params)) {
174
            $params = http_build_query($params);
175
            // GETの場合はstream_context_createでクエリを渡しても有効にならないため
176
            // URLにクエリストリングを付けることで対処
177
            if ($method === "GET") {
178
                $url .= "?" . $params;
179
            }
180
        }
181
        if (empty($headers) && ($method === "POST" || $method === "PUT")) {
182
            $contentLength = !is_string($params) ? 0 : strlen($params);
183
            $headers = [
184
                "Content-Type: application/x-www-form-urlencoded",
185
                "Content-Length: " . $contentLength
186
            ];
187
        }
188
        $request = [
189
            "method"  => $method,
190
            "content" => $params,
191
            "timeout" => $this->timeout
192
        ];
193
        // Proxy設定
194
        if ($this->proxy_host && $this->proxy_port) {
195
            $this->proxy($request);
196
        }
197
        // Basic認証
198
        if ($this->basic_auth_id && $this->basic_auth_password) {
199
            $this->basicAuth($headers);
200
        }
201
        if (!empty($headers)) {
202
            $request["header"] = implode("\r\n", $headers);
203
        }
204
        // レスポンス
205
        $response = @file_get_contents($url, false, stream_context_create(["http" => $request]));
206
207
        if (!isset($http_response_header)) {
208
            $hasHeader = @get_headers($url);
209
            if ($hasHeader === false) { // ヘッダを持たない場合、存在しないURL
210
                $this->status_code = 404;
211
                $this->logger->error("URL not found: " . $url);
212
            } else { // ヘッダを持つ場合はタイムアウトが発生
213
                $this->status_code = 408;
214
                $this->logger->error("Request timeout: " . $url);
0 ignored issues
show
Bug Best Practice introduced by
The property logger does not exist on WebStream\Module\HttpClient. Since you implemented __get, consider adding a @property annotation.
Loading history...
215
            }
216
217
            return null;
218
        } else {
219
            $this->responseHeader = $http_response_header;
220
        }
221
222
        // ヘッダ情報を取得
223
        foreach ($this->responseHeader as $value) {
224
            // Content-Type
225
            if (preg_match('/^Content-Type:\s.+/', $value)) {
226
                $this->content_type = $value;
227
            }
228
            // ステータスコード
229
            if (preg_match('/^HTTP\/.+\s([0-9]{3})/', $this->responseHeader[0], $matches)) {
230
                $this->status_code = intval($matches[1]);
231
            }
232
        }
233
234
        if ($this->status_code === 200) { // HTTP通信の結果が200
235
            $this->logger->info("HTTP {$method} success({$this->status_code}): {$url}");
236
237
            return $response;
238
        } else { // HTTP通信の結果が200以外
239
            if ($this->status_code === null) {
240
                $this->status_code = 500;
241
            }
242
            $this->logger->error("HTTP {$method} failure({$this->status_code}): {$url}");
243
244
            return null;
245
        }
246
    }
247
248
    /**
249
     * 配列から安全に値を取得する
250
     * @param array<string> オプション配列
251
     * @param string 配列キー
252
     * @param string or Integer デフォルト値
253
     * @return mixed オプション配列の値
254
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment オプション配列 at position 0 could not be parsed: Unknown type name 'オプション配列' at position 0 in オプション配列.
Loading history...
255
    private function getOptionParameter($options, $key, $default_value = null)
256
    {
257
        return array_key_exists($key, $options) ? $options[$key] : $default_value;
258
    }
259
}
260