| Total Complexity | 61 |
| Total Lines | 332 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like HttpClientBase often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use HttpClientBase, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 41 | class HttpClientBase |
||
| 42 | { |
||
| 43 | const CRLF = "\r\n"; |
||
| 44 | |||
| 45 | const HTTP_OK = 200; |
||
| 46 | const HTTP_ACCEPTED = 202; |
||
| 47 | const HTTP_MULTIPLE_CHOICES = 300; |
||
| 48 | const HTTP_BAD_REQUEST = 400; |
||
| 49 | const HTTP_UNAUTHORIZED = 401; |
||
| 50 | |||
| 51 | protected function stringStartsWith($source, $subString) |
||
| 52 | { |
||
| 53 | return 0 === mb_strpos($source, $subString, 0, Constraints::UTF_8); |
||
| 54 | } |
||
| 55 | |||
| 56 | protected function stringEndsWith($source, $subString) |
||
| 57 | { |
||
| 58 | $sourceLength = StringUtils::length($source); |
||
| 59 | $subStringLength = StringUtils::length($subString); |
||
| 60 | $subStringIndex = $sourceLength - $subStringLength; |
||
| 61 | |||
| 62 | if ($subStringLength < 0) { |
||
| 63 | return false; |
||
| 64 | } |
||
| 65 | |||
| 66 | $newString = (mb_substr($source, $subStringIndex, $subStringLength, Constraints::UTF_8)); |
||
| 67 | |||
| 68 | return $newString === $subString; |
||
| 69 | } |
||
| 70 | |||
| 71 | protected function getValueFromArray(array $array, $index, $defaultValue = null) |
||
| 74 | } |
||
| 75 | |||
| 76 | protected function getHttpResponseFromUrl($url, $context) |
||
| 77 | { |
||
| 78 | $http_response_header = null; |
||
|
|
|||
| 79 | |||
| 80 | $contents = @file_get_contents($url, false, $context); |
||
| 81 | if (false === $contents) { |
||
| 82 | throw new EasyPdfCloudApiException(0, 'Unable to communicate to the server'); |
||
| 83 | } |
||
| 84 | |||
| 85 | return array( |
||
| 86 | 'header' => $http_response_header, |
||
| 87 | 'contents' => $contents, |
||
| 88 | ); |
||
| 89 | } |
||
| 90 | |||
| 91 | protected function mapFirstLineHeaders($header) |
||
| 92 | { |
||
| 93 | $array = array(); |
||
| 94 | |||
| 95 | $keyValueMap = array_map('trim', explode(':', $header, 2)); |
||
| 96 | $headerName = (count($keyValueMap) >= 1 ? $keyValueMap[0] : null); |
||
| 97 | $headerValue = (count($keyValueMap) >= 2 ? $keyValueMap[1] : null); |
||
| 98 | |||
| 99 | $firstLineMap = array_map('trim', explode(' ', $headerName, 3)); |
||
| 100 | |||
| 101 | if (count($firstLineMap) >= 1) { |
||
| 102 | $httpVersionHeader = $firstLineMap[0]; |
||
| 103 | $httpVersionMap = array_map('trim', explode('/', $httpVersionHeader, 2)); |
||
| 104 | |||
| 105 | if (count($httpVersionMap) >= 2) { |
||
| 106 | $headerNameLC = 'http-version'; |
||
| 107 | $headerValue = $httpVersionMap[1]; |
||
| 108 | $array += array($headerNameLC => $headerValue); |
||
| 109 | } |
||
| 110 | |||
| 111 | if (count($firstLineMap) >= 2) { |
||
| 112 | $headerNameLC = 'status-code'; |
||
| 113 | $headerValue = $firstLineMap[1]; |
||
| 114 | $array += array($headerNameLC => $headerValue); |
||
| 115 | |||
| 116 | if (count($firstLineMap) >= 3) { |
||
| 117 | $headerNameLC = 'status-description'; |
||
| 118 | $headerValue = $firstLineMap[2]; |
||
| 119 | $array += array($headerNameLC => $headerValue); |
||
| 120 | } |
||
| 121 | } |
||
| 122 | } |
||
| 123 | |||
| 124 | return $array; |
||
| 125 | } |
||
| 126 | |||
| 127 | protected function mapHttpHeaders($headers) |
||
| 128 | { |
||
| 129 | $headersCount = count($headers); |
||
| 130 | if (0 === $headersCount) { |
||
| 131 | return array(); |
||
| 132 | } |
||
| 133 | |||
| 134 | $header = $headers[0]; |
||
| 135 | $array = $this->mapFirstLineHeaders($header); |
||
| 136 | |||
| 137 | for ($i = 1; $i < $headersCount; ++$i) { |
||
| 138 | $header = $headers[$i]; |
||
| 139 | |||
| 140 | $keyValueMap = array_map('trim', explode(':', $header, 2)); |
||
| 141 | $headerName = (count($keyValueMap) >= 1 ? $keyValueMap[0] : null); |
||
| 142 | $headerValue = (count($keyValueMap) >= 2 ? $keyValueMap[1] : null); |
||
| 143 | |||
| 144 | if (null !== $headerName) { |
||
| 145 | $headerNameLC = mb_strtolower($headerName, Constraints::UTF_8); |
||
| 146 | $array += array($headerNameLC => $headerValue); |
||
| 147 | } |
||
| 148 | } |
||
| 149 | |||
| 150 | return $array; |
||
| 151 | } |
||
| 152 | |||
| 153 | protected function getStatusCodeFromResponse($headers) |
||
| 154 | { |
||
| 155 | if (!isset($headers['status-code'])) { |
||
| 156 | return 0; |
||
| 157 | } |
||
| 158 | |||
| 159 | $statusCode = (int) $headers['status-code']; |
||
| 160 | |||
| 161 | return $statusCode; |
||
| 162 | } |
||
| 163 | |||
| 164 | protected function isSuccessfulResponse($headers) |
||
| 165 | { |
||
| 166 | $statusCode = $this->getStatusCodeFromResponse($headers); |
||
| 167 | |||
| 168 | return $statusCode >= self::HTTP_OK && $statusCode < self::HTTP_MULTIPLE_CHOICES; |
||
| 169 | } |
||
| 170 | |||
| 171 | protected function getFileNameFromContentDisposisionHeader($contentDisposition) |
||
| 172 | { |
||
| 173 | if (!isset($contentDisposition)) { |
||
| 174 | return null; |
||
| 175 | } |
||
| 176 | |||
| 177 | $colonSeparatedList = array_map('trim', explode(';', $contentDisposition)); |
||
| 178 | $array = array(); |
||
| 179 | |||
| 180 | foreach ($colonSeparatedList as $item) { |
||
| 181 | $separatedList = array_map('trim', explode('=', $item, 2)); |
||
| 182 | |||
| 183 | if (count($separatedList) >= 2) { |
||
| 184 | $nameLC = mb_strtolower($separatedList[0], Constraints::UTF_8); |
||
| 185 | $value = trim($separatedList[1], '"'); |
||
| 186 | |||
| 187 | $array += array($nameLC => $value); |
||
| 188 | } |
||
| 189 | } |
||
| 190 | |||
| 191 | if (isset($array['filename*'])) { |
||
| 192 | $fileName = $array['filename*']; |
||
| 193 | |||
| 194 | $utf8Prefix = 'utf-8\'\''; |
||
| 195 | |||
| 196 | if ($this->stringStartsWith($fileName, $utf8Prefix)) { |
||
| 197 | // trim utf8 prefix |
||
| 198 | $prefixLength = mb_strlen($utf8Prefix, Constraints::UTF_8); |
||
| 199 | $fileName = mb_substr($fileName, $prefixLength, null, Constraints::UTF_8); |
||
| 200 | } |
||
| 201 | |||
| 202 | // URL decode and return |
||
| 203 | $fileName = urldecode($fileName); |
||
| 204 | |||
| 205 | return $fileName; |
||
| 206 | } elseif (isset($array['filename'])) { |
||
| 207 | $fileName = $array['filename']; |
||
| 208 | |||
| 209 | $base64Prefix = '=?utf-8?B?'; |
||
| 210 | $base64Postfix = '?='; |
||
| 211 | |||
| 212 | if ($this->stringStartsWith($fileName, $base64Prefix)) { |
||
| 213 | // trim base64 prefix |
||
| 214 | $prefixLength = mb_strlen($base64Prefix, Constraints::UTF_8); |
||
| 215 | $fileName = mb_substr($fileName, $prefixLength, null, Constraints::UTF_8); |
||
| 216 | |||
| 217 | if ($this->stringEndsWith($fileName, $base64Postfix)) { |
||
| 218 | // trim base64 postfix |
||
| 219 | $fileNameLength = mb_strlen($fileName, Constraints::UTF_8); |
||
| 220 | $postfixLength = mb_strlen($base64Postfix, Constraints::UTF_8); |
||
| 221 | $substrLength = $fileNameLength - $postfixLength; |
||
| 222 | $fileName = mb_substr($fileName, 0, $substrLength, Constraints::UTF_8); |
||
| 223 | } |
||
| 224 | |||
| 225 | // base64 decode and return |
||
| 226 | $fileName = base64_decode($fileName, true); |
||
| 227 | |||
| 228 | return $fileName; |
||
| 229 | } |
||
| 230 | |||
| 231 | // URL decode and return |
||
| 232 | $fileName = urldecode($fileName); |
||
| 233 | |||
| 234 | return $fileName; |
||
| 235 | } |
||
| 236 | |||
| 237 | return null; |
||
| 238 | } |
||
| 239 | |||
| 240 | protected function parseWwwAuthenticateResonseHeader($wwwAuthenticate) |
||
| 241 | { |
||
| 242 | $spaceSeparatedList = array_map('trim', explode(' ', $wwwAuthenticate)); |
||
| 243 | $commaSeparatedList = array(); |
||
| 244 | $array = array(); |
||
| 245 | |||
| 246 | foreach ($spaceSeparatedList as $item) { |
||
| 247 | $separatedList = array_map('trim', explode(',', $item)); |
||
| 248 | |||
| 249 | if (count($separatedList) >= 2) { |
||
| 250 | $commaSeparatedList = array_merge($commaSeparatedList, $separatedList); |
||
| 251 | } |
||
| 252 | } |
||
| 253 | |||
| 254 | foreach ($commaSeparatedList as $item) { |
||
| 255 | $separatedList = array_map('trim', explode('=', $item, 2)); |
||
| 256 | |||
| 257 | if (count($separatedList) >= 2) { |
||
| 258 | $nameLC = mb_strtolower(trim($separatedList[0]), Constraints::UTF_8); |
||
| 259 | $value = urldecode(trim(trim($separatedList[1]), '"')); |
||
| 260 | |||
| 261 | $array += array($nameLC => $value); |
||
| 262 | } |
||
| 263 | } |
||
| 264 | |||
| 265 | return $array; |
||
| 266 | } |
||
| 267 | |||
| 268 | protected function checkWwwAuthenticateResponseHeader($headers) |
||
| 269 | { |
||
| 270 | $statusCode = $this->getStatusCodeFromResponse($headers); |
||
| 271 | |||
| 272 | if (self::HTTP_BAD_REQUEST !== $statusCode && self::HTTP_UNAUTHORIZED !== $statusCode) { |
||
| 273 | return; |
||
| 274 | } |
||
| 275 | |||
| 276 | if (!isset($headers['www-authenticate'])) { |
||
| 277 | return; |
||
| 278 | } |
||
| 279 | |||
| 280 | $wwwAuthenticate = $headers['www-authenticate']; |
||
| 281 | $wwwAuthenticateMap = $this->parseWwwAuthenticateResonseHeader($wwwAuthenticate); |
||
| 282 | |||
| 283 | if (isset($wwwAuthenticateMap['error'])) { |
||
| 284 | $error = $wwwAuthenticateMap['error']; |
||
| 285 | |||
| 286 | $errorDescription = ''; |
||
| 287 | if (isset($wwwAuthenticateMap['error_description'])) { |
||
| 288 | $errorDescription = $wwwAuthenticateMap['error_description']; |
||
| 289 | } |
||
| 290 | |||
| 291 | throw new ApiAuthorizationException($statusCode, $error, $errorDescription); |
||
| 292 | } |
||
| 293 | } |
||
| 294 | |||
| 295 | protected function needsToRefreshToken($headers) |
||
| 309 | } |
||
| 310 | |||
| 311 | protected function decodeJsonFromResponse($headers, $contents, $failIfNotJson) |
||
| 312 | { |
||
| 313 | if (!isset($headers['content-type'])) { |
||
| 341 | } |
||
| 342 | |||
| 343 | protected function handleResponse($headers, $contents = null) |
||
| 344 | { |
||
| 345 | if ($this->isSuccessfulResponse($headers)) { |
||
| 373 | } |
||
| 374 | } |
||
| 375 |