Passed
Push — v6 ( 95b370...25ce72 )
by 光春
03:13
created

AliyunClient::curl()   B

Complexity

Conditions 11
Paths 48

Size

Total Lines 52
Code Lines 30

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 11
eloc 30
c 1
b 0
f 0
nc 48
nop 2
dl 0
loc 52
rs 7.3166

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
class AliyunClient
3
{
4
	public $accessKeyId;
5
6
	public $accessKeySecret;
7
8
	public $serverUrl = "http://ecs.aliyuncs.com/";
9
10
	public $format = "json";
11
12
	public $connectTimeout = 3000;//3秒
13
14
	public $readTimeout = 80000;//80秒
15
16
	/** 是否打开入参check**/
17
	public $checkRequest = true;
18
19
	protected $signatureMethod = "HMAC-SHA1";
20
21
	protected $signatureVersion = "1.0";
22
	
23
    protected  $dateTimeFormat = 'Y-m-d\TH:i:s\Z'; // ISO8601规范
24
	
25
	protected $sdkVersion = "1.0";
26
27
	public function execute($request)
28
	{
29
		if($this->checkRequest) {
30
			try {
31
				$request->check();
32
			} catch (Exception $e) {
33
				$result->code = $e->getCode();
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $result seems to be never defined.
Loading history...
34
				$result->message = $e->getMessage();
35
				return $result;
36
			}
37
		}
38
		//获取业务参数
39
		$apiParams = $request->getApiParas();
40
		//组装系统参数
41
		$apiParams["AccessKeyId"] = $this->accessKeyId;
42
		$apiParams["Format"] = $this->format;//
43
		$apiParams["SignatureMethod"] = $this->signatureMethod;
44
		$apiParams["SignatureVersion"] = $this->signatureVersion;
45
		$apiParams["SignatureNonce"] = uniqid();
46
		date_default_timezone_set("GMT");
47
		$apiParams["TimeStamp"] = date($this->dateTimeFormat);
48
		$apiParams["partner_id"] = $this->sdkVersion;
49
		
50
	    $apiNameArray =	split("\.", $request->getApiMethodName());
0 ignored issues
show
Deprecated Code introduced by
The function split() has been deprecated: 5.3.0 Use preg_split() instead ( Ignorable by Annotation )

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

50
	    $apiNameArray =	/** @scrutinizer ignore-deprecated */ split("\.", $request->getApiMethodName());

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
51
		$apiParams["Action"] = $apiNameArray[3];
52
		$apiParams["Version"] = $apiNameArray[4];
53
		//签名
54
		$apiParams["Signature"] = $this->computeSignature($apiParams, $this->accessKeySecret);
55
56
		//系统参数放入GET请求串
57
		$requestUrl = rtrim($this->serverUrl,"/") . "/?";
58
		foreach ($apiParams as $apiParamKey => $apiParamValue)
59
		{
60
			$requestUrl .= "$apiParamKey=" . urlencode($apiParamValue) . "&";
61
		}
62
		$requestUrl = substr($requestUrl, 0, -1);
63
		//发起HTTP请求
64
		try
65
		{
66
			$resp = $this->curl($requestUrl, null);
67
		}
68
		catch (Exception $e)
69
		{
70
			$this->logCommunicationError($apiParams["Action"],$requestUrl,"HTTP_ERROR_" . $e->getCode(),$e->getMessage());
71
			if ("json" == $this->format)
72
			{
73
				return  json_decode($e->getMessage());
74
			}
75
			else if("xml" == $this->format)
76
			{
77
				return  @simplexml_load_string($e->getMessage());
78
			}
79
	    }
80
81
		//解析API返回结果
82
		$respWellFormed = false;
83
		if ("json" == $this->format)
84
		{
85
			$respObject = json_decode($resp);
86
			if (null !== $respObject)
87
			{
88
				$respWellFormed = true;
89
			}
90
		}
91
		else if("xml" == $this->format)
92
		{
93
			$respObject = @simplexml_load_string($resp);
94
			if (false !== $respObject)
95
			{
96
				$respWellFormed = true;
97
			}
98
		}
99
100
		//返回的HTTP文本不是标准JSON或者XML,记下错误日志
101
		if (false === $respWellFormed)
102
		{
103
			$this->logCommunicationError($apiParams["Action"],$requestUrl,"HTTP_RESPONSE_NOT_WELL_FORMED",$resp);
104
			$result->code = 0;
105
			$result->message = "HTTP_RESPONSE_NOT_WELL_FORMED";
106
			return $result;
107
		}
108
109
		//如果TOP返回了错误码,记录到业务错误日志中
110
		if (isset($respObject->code))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $respObject does not seem to be defined for all execution paths leading up to this point.
Loading history...
111
		{
112
			$logger = new LtLogger;
0 ignored issues
show
Bug introduced by
The type LtLogger was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
113
			$logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/') . '/' . "logs/top_biz_err_" . $this->appkey . "_" . date("Y-m-d") . ".log";
0 ignored issues
show
Bug Best Practice introduced by
The property appkey does not exist on AliyunClient. Did you maybe forget to declare it?
Loading history...
114
			$logger->log(array(
115
				date("Y-m-d H:i:s"),
116
				$resp
117
			));
118
		}
119
		return $respObject;
120
	}
121
122
	public function exec($paramsArray)
123
	{
124
		if (!isset($paramsArray["Action"]))
125
		{
126
			trigger_error("No api name passed");
127
		}
128
		$inflector = new LtInflector;
0 ignored issues
show
Bug introduced by
The type LtInflector was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
129
		$inflector->conf["separator"] = ".";
130
		$requestClassName = ucfirst($inflector->camelize(substr($paramsArray["Action"], 7))) . "Request";
131
		if (!class_exists($requestClassName))
132
		{
133
			trigger_error("No such api: " . $paramsArray["Action"]);
134
		}
135
136
		$req = new $requestClassName;
137
		foreach($paramsArray as $paraKey => $paraValue)
138
		{
139
			$inflector->conf["separator"] = "_";
140
			$setterMethodName = $inflector->camelize($paraKey);
141
			$inflector->conf["separator"] = ".";
142
			$setterMethodName = "set" . $inflector->camelize($setterMethodName);
143
			if (method_exists($req, $setterMethodName))
144
			{
145
				$req->$setterMethodName($paraValue);
146
			}
147
		}
148
		return $this->execute($req, $session);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $session seems to be never defined.
Loading history...
Unused Code introduced by
The call to AliyunClient::execute() has too many arguments starting with $session. ( Ignorable by Annotation )

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

148
		return $this->/** @scrutinizer ignore-call */ execute($req, $session);

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...
149
	}
150
	
151
	protected function percentEncode($str)
152
	{
153
	    // 使用urlencode编码后,将"+","*","%7E"做替换即满足 API规定的编码规范
154
	    $res = urlencode($str);
155
	    $res = preg_replace('/\+/', '%20', $res);
156
	    $res = preg_replace('/\*/', '%2A', $res);
157
	    $res = preg_replace('/%7E/', '~', $res);
158
	    return $res;
159
	}
160
	
161
	protected function computeSignature($parameters, $accessKeySecret)
162
	{
163
	    // 将参数Key按字典顺序排序
164
	    ksort($parameters);
165
	
166
	    // 生成规范化请求字符串
167
	    $canonicalizedQueryString = '';
168
	    foreach($parameters as $key => $value)
169
	    {
170
		$canonicalizedQueryString .= '&' . $this->percentEncode($key) 
171
		    . '=' . $this->percentEncode($value);
172
	    }
173
	
174
	    // 生成用于计算签名的字符串 stringToSign
175
	    $stringToSign = 'GET&%2F&' . $this->percentencode(substr($canonicalizedQueryString, 1));
176
	
177
	    // 计算签名,注意accessKeySecret后面要加上字符'&'
178
	    $signature = base64_encode(hash_hmac('sha1', $stringToSign, $accessKeySecret . '&', true));
179
	    return $signature;
180
	}
181
	
182
    public function curl($url, $postFields = null)
183
	{
184
		$ch = curl_init();
185
		curl_setopt($ch, CURLOPT_URL, $url);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_setopt() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

185
		curl_setopt(/** @scrutinizer ignore-type */ $ch, CURLOPT_URL, $url);
Loading history...
186
		curl_setopt($ch, CURLOPT_FAILONERROR, false);
187
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
188
		if ($this->readTimeout) {
189
			curl_setopt($ch, CURLOPT_TIMEOUT, $this->readTimeout);
190
		}
191
		if ($this->connectTimeout) {
192
			curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $this->connectTimeout);
193
		}
194
		//https 请求
195
		if(strlen($url) > 5 && strtolower(substr($url,0,5)) == "https" ) {
196
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
197
			curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
198
		}
199
200
		if (is_array($postFields) && 0 < count($postFields))
201
		{
202
			$postBodyString = "";
203
			$postMultipart = false;
204
			foreach ($postFields as $k => $v)
205
			{
206
				if("@" != substr($v, 0, 1))//判断是不是文件上传
207
				{
208
					$postBodyString .= "$k=" . urlencode($v) . "&"; 
209
				}
210
				else//文件上传用multipart/form-data,否则用www-form-urlencoded
211
				{
212
					$postMultipart = true;
213
				}
214
			}
215
			unset($k, $v);
216
			curl_setopt($ch, CURLOPT_POST, true);
217
			if ($postMultipart)
218
			{
219
				curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
220
			}
221
			else
222
			{
223
				curl_setopt($ch, CURLOPT_POSTFIELDS, substr($postBodyString,0,-1));
224
			}
225
		}
226
		$reponse = curl_exec($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_exec() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

226
		$reponse = curl_exec(/** @scrutinizer ignore-type */ $ch);
Loading history...
227
		
228
		if (curl_errno($ch))
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_errno() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

228
		if (curl_errno(/** @scrutinizer ignore-type */ $ch))
Loading history...
229
		{
230
			throw new Exception(curl_error($ch),0);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_error() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

230
			throw new Exception(curl_error(/** @scrutinizer ignore-type */ $ch),0);
Loading history...
231
		}
232
		curl_close($ch);
0 ignored issues
show
Bug introduced by
It seems like $ch can also be of type false; however, parameter $ch of curl_close() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

232
		curl_close(/** @scrutinizer ignore-type */ $ch);
Loading history...
233
		return $reponse;
234
	}
235
236
	protected function logCommunicationError($apiName, $requestUrl, $errorCode, $responseTxt)
237
	{
238
		$localIp = isset($_SERVER["SERVER_ADDR"]) ? $_SERVER["SERVER_ADDR"] : "CLI";
239
		$logger = new LtLogger;
240
		$logger->conf["log_file"] = rtrim(TOP_SDK_WORK_DIR, '\\/') . '/' . "logs/top_comm_err_" . $this->accessKeyId . "_" . date("Y-m-d") . ".log";
241
		$logger->conf["separator"] = "^_^";
242
		$logData = array(
243
		date("Y-m-d H:i:s"),
244
		$apiName,
245
		$this->accessKeyId,
246
		$localIp,
247
		PHP_OS,
248
		$this->sdkVersion,
249
		$requestUrl,
250
		$errorCode,
251
		str_replace("\n","",$responseTxt)
252
		);
253
		$logger->log($logData);
254
	}
255
}
256