PageRenderTime 69ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/abraham/twitteroauth/src/TwitterOAuth.php

https://gitlab.com/Hungcis/testvagrant
PHP | 448 lines | 241 code | 40 blank | 167 comment | 20 complexity | 23b15f9194af7d670af591eccb4e65af MD5 | raw file
  1. <?php
  2. /**
  3. * The most popular PHP library for use with the Twitter OAuth REST API.
  4. *
  5. * @license MIT
  6. */
  7. namespace Abraham\TwitterOAuth;
  8. use Abraham\TwitterOAuth\Util\JsonDecoder;
  9. /**
  10. * TwitterOAuth class for interacting with the Twitter API.
  11. *
  12. * @author Abraham Williams <abraham@abrah.am>
  13. */
  14. class TwitterOAuth extends Config
  15. {
  16. const API_VERSION = '1.1';
  17. const API_HOST = 'https://api.twitter.com';
  18. const UPLOAD_HOST = 'https://upload.twitter.com';
  19. const UPLOAD_CHUNK = 40960; // 1024 * 40
  20. /** @var Response details about the result of the last request */
  21. private $response;
  22. /** @var string|null Application bearer token */
  23. private $bearer;
  24. /** @var Consumer Twitter application details */
  25. private $consumer;
  26. /** @var Token|null User access token details */
  27. private $token;
  28. /** @var HmacSha1 OAuth 1 signature type used by Twitter */
  29. private $signatureMethod;
  30. /**
  31. * Constructor
  32. *
  33. * @param string $consumerKey The Application Consumer Key
  34. * @param string $consumerSecret The Application Consumer Secret
  35. * @param string|null $oauthToken The Client Token (optional)
  36. * @param string|null $oauthTokenSecret The Client Token Secret (optional)
  37. */
  38. public function __construct($consumerKey, $consumerSecret, $oauthToken = null, $oauthTokenSecret = null)
  39. {
  40. $this->resetLastResponse();
  41. $this->signatureMethod = new HmacSha1();
  42. $this->consumer = new Consumer($consumerKey, $consumerSecret);
  43. if (!empty($oauthToken) && !empty($oauthTokenSecret)) {
  44. $this->token = new Token($oauthToken, $oauthTokenSecret);
  45. }
  46. if (empty($oauthToken) && !empty($oauthTokenSecret)) {
  47. $this->bearer = $oauthTokenSecret;
  48. }
  49. }
  50. /**
  51. * @param string $oauthToken
  52. * @param string $oauthTokenSecret
  53. */
  54. public function setOauthToken($oauthToken, $oauthTokenSecret)
  55. {
  56. $this->token = new Token($oauthToken, $oauthTokenSecret);
  57. }
  58. /**
  59. * @return string|null
  60. */
  61. public function getLastApiPath()
  62. {
  63. return $this->response->getApiPath();
  64. }
  65. /**
  66. * @return int
  67. */
  68. public function getLastHttpCode()
  69. {
  70. return $this->response->getHttpCode();
  71. }
  72. /**
  73. * @return array
  74. */
  75. public function getLastXHeaders()
  76. {
  77. return $this->response->getXHeaders();
  78. }
  79. /**
  80. * @return array|object|null
  81. */
  82. public function getLastBody()
  83. {
  84. return $this->response->getBody();
  85. }
  86. /**
  87. * Resets the last response cache.
  88. */
  89. public function resetLastResponse()
  90. {
  91. $this->response = new Response();
  92. }
  93. public function url($path, array $parameters)
  94. {
  95. $this->resetLastResponse();
  96. $this->response->setApiPath($path);
  97. $query = http_build_query($parameters);
  98. return sprintf('%s/%s?%s', self::API_HOST, $path, $query);
  99. }
  100. /**
  101. * Make /oauth/* requests to the API.
  102. *
  103. * @param string $path
  104. * @param array $parameters
  105. *
  106. * @return array
  107. * @throws TwitterOAuthException
  108. */
  109. public function oauth($path, array $parameters = [])
  110. {
  111. $response = [];
  112. $this->resetLastResponse();
  113. $this->response->setApiPath($path);
  114. $url = sprintf('%s/%s', self::API_HOST, $path);
  115. $result = $this->oAuthRequest($url, 'POST', $parameters);
  116. if ($this->getLastHttpCode() != 200) {
  117. throw new TwitterOAuthException($result);
  118. }
  119. parse_str($result, $response);
  120. $this->response->setBody($response);
  121. return $response;
  122. }
  123. /**
  124. * Make /oauth2/* requests to the API.
  125. *
  126. * @param string $path
  127. * @param array $parameters
  128. *
  129. * @return array|object
  130. */
  131. public function oauth2($path, array $parameters = [])
  132. {
  133. $method = 'POST';
  134. $this->resetLastResponse();
  135. $this->response->setApiPath($path);
  136. $url = sprintf('%s/%s', self::API_HOST, $path);
  137. $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
  138. $authorization = 'Authorization: Basic ' . $this->encodeAppAuthorization($this->consumer);
  139. $result = $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
  140. $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
  141. $this->response->setBody($response);
  142. return $response;
  143. }
  144. /**
  145. * Make GET requests to the API.
  146. *
  147. * @param string $path
  148. * @param array $parameters
  149. *
  150. * @return array|object
  151. */
  152. public function get($path, array $parameters = [])
  153. {
  154. return $this->http('GET', self::API_HOST, $path, $parameters);
  155. }
  156. /**
  157. * Make POST requests to the API.
  158. *
  159. * @param string $path
  160. * @param array $parameters
  161. *
  162. * @return array|object
  163. */
  164. public function post($path, array $parameters = [])
  165. {
  166. return $this->http('POST', self::API_HOST, $path, $parameters);
  167. }
  168. /**
  169. * Make DELETE requests to the API.
  170. *
  171. * @param string $path
  172. * @param array $parameters
  173. *
  174. * @return array|object
  175. */
  176. public function delete($path, array $parameters = [])
  177. {
  178. return $this->http('DELETE', self::API_HOST, $path, $parameters);
  179. }
  180. /**
  181. * Make PUT requests to the API.
  182. *
  183. * @param string $path
  184. * @param array $parameters
  185. *
  186. * @return array|object
  187. */
  188. public function put($path, array $parameters = [])
  189. {
  190. return $this->http('PUT', self::API_HOST, $path, $parameters);
  191. }
  192. /**
  193. * Upload media to upload.twitter.com.
  194. *
  195. * @param string $path
  196. * @param array $parameters
  197. * @param boolean $chunked
  198. *
  199. * @return array|object
  200. */
  201. public function upload($path, array $parameters = [], $chunked = false)
  202. {
  203. if ($chunked) {
  204. return $this->uploadMediaChunked($path, $parameters);
  205. } else {
  206. return $this->uploadMediaNotChunked($path, $parameters);
  207. }
  208. }
  209. /**
  210. * Private method to upload media (not chunked) to upload.twitter.com.
  211. *
  212. * @param string $path
  213. * @param array $parameters
  214. *
  215. * @return array|object
  216. */
  217. private function uploadMediaNotChunked($path, array $parameters)
  218. {
  219. $file = file_get_contents($parameters['media']);
  220. $base = base64_encode($file);
  221. $parameters['media'] = $base;
  222. return $this->http('POST', self::UPLOAD_HOST, $path, $parameters);
  223. }
  224. /**
  225. * Private method to upload media (chunked) to upload.twitter.com.
  226. *
  227. * @param string $path
  228. * @param array $parameters
  229. *
  230. * @return array|object
  231. */
  232. private function uploadMediaChunked($path, array $parameters)
  233. {
  234. // Init
  235. $init = $this->http('POST', self::UPLOAD_HOST, $path, [
  236. 'command' => 'INIT',
  237. 'media_type' => $parameters['media_type'],
  238. 'total_bytes' => filesize($parameters['media'])
  239. ]);
  240. // Append
  241. $segment_index = 0;
  242. $media = fopen($parameters['media'], 'rb');
  243. while (!feof($media))
  244. {
  245. $this->http('POST', self::UPLOAD_HOST, 'media/upload', [
  246. 'command' => 'APPEND',
  247. 'media_id' => $init->media_id_string,
  248. 'segment_index' => $segment_index++,
  249. 'media_data' => base64_encode(fread($media, self::UPLOAD_CHUNK))
  250. ]);
  251. }
  252. fclose($media);
  253. // Finalize
  254. $finalize = $this->http('POST', self::UPLOAD_HOST, 'media/upload', [
  255. 'command' => 'FINALIZE',
  256. 'media_id' => $init->media_id_string
  257. ]);
  258. return $finalize;
  259. }
  260. /**
  261. * @param string $method
  262. * @param string $host
  263. * @param string $path
  264. * @param array $parameters
  265. *
  266. * @return array|object
  267. */
  268. private function http($method, $host, $path, array $parameters)
  269. {
  270. $this->resetLastResponse();
  271. $url = sprintf('%s/%s/%s.json', $host, self::API_VERSION, $path);
  272. $this->response->setApiPath($path);
  273. $result = $this->oAuthRequest($url, $method, $parameters);
  274. $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
  275. $this->response->setBody($response);
  276. return $response;
  277. }
  278. /**
  279. * Format and sign an OAuth / API request
  280. *
  281. * @param string $url
  282. * @param string $method
  283. * @param array $parameters
  284. *
  285. * @return string
  286. * @throws TwitterOAuthException
  287. */
  288. private function oAuthRequest($url, $method, array $parameters)
  289. {
  290. $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
  291. if (array_key_exists('oauth_callback', $parameters)) {
  292. // Twitter doesn't like oauth_callback as a parameter.
  293. unset($parameters['oauth_callback']);
  294. }
  295. if ($this->bearer === null) {
  296. $request->signRequest($this->signatureMethod, $this->consumer, $this->token);
  297. $authorization = $request->toHeader();
  298. } else {
  299. $authorization = 'Authorization: Bearer ' . $this->bearer;
  300. }
  301. return $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
  302. }
  303. /**
  304. * Make an HTTP request
  305. *
  306. * @param string $url
  307. * @param string $method
  308. * @param string $authorization
  309. * @param array $postfields
  310. *
  311. * @return string
  312. * @throws TwitterOAuthException
  313. */
  314. private function request($url, $method, $authorization, array $postfields)
  315. {
  316. /* Curl settings */
  317. $options = [
  318. // CURLOPT_VERBOSE => true,
  319. CURLOPT_CAINFO => __DIR__ . DIRECTORY_SEPARATOR . 'cacert.pem',
  320. CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
  321. CURLOPT_HEADER => true,
  322. CURLOPT_HTTPHEADER => ['Accept: application/json', $authorization, 'Expect:'],
  323. CURLOPT_RETURNTRANSFER => true,
  324. CURLOPT_SSL_VERIFYHOST => 2,
  325. CURLOPT_SSL_VERIFYPEER => true,
  326. CURLOPT_TIMEOUT => $this->timeout,
  327. CURLOPT_URL => $url,
  328. CURLOPT_USERAGENT => $this->userAgent,
  329. ];
  330. /* Remove CACert file when in a PHAR file. */
  331. if (!empty(\Phar::running(false))) {
  332. unset($options[CURLOPT_CAINFO]);
  333. }
  334. if($this->gzipEncoding) {
  335. $options[CURLOPT_ENCODING] = 'gzip';
  336. }
  337. if (!empty($this->proxy)) {
  338. $options[CURLOPT_PROXY] = $this->proxy['CURLOPT_PROXY'];
  339. $options[CURLOPT_PROXYUSERPWD] = $this->proxy['CURLOPT_PROXYUSERPWD'];
  340. $options[CURLOPT_PROXYPORT] = $this->proxy['CURLOPT_PROXYPORT'];
  341. $options[CURLOPT_PROXYAUTH] = CURLAUTH_BASIC;
  342. $options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP;
  343. }
  344. switch ($method) {
  345. case 'GET':
  346. break;
  347. case 'POST':
  348. $options[CURLOPT_POST] = true;
  349. $options[CURLOPT_POSTFIELDS] = Util::buildHttpQuery($postfields);
  350. break;
  351. case 'DELETE':
  352. $options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
  353. break;
  354. case 'PUT':
  355. $options[CURLOPT_CUSTOMREQUEST] = 'PUT';
  356. break;
  357. }
  358. if (in_array($method, ['GET', 'PUT', 'DELETE']) && !empty($postfields)) {
  359. $options[CURLOPT_URL] .= '?' . Util::buildHttpQuery($postfields);
  360. }
  361. $curlHandle = curl_init();
  362. curl_setopt_array($curlHandle, $options);
  363. $response = curl_exec($curlHandle);
  364. // Throw exceptions on cURL errors.
  365. if (curl_errno($curlHandle) > 0) {
  366. throw new TwitterOAuthException(curl_error($curlHandle), curl_errno($curlHandle));
  367. }
  368. $this->response->setHttpCode(curl_getinfo($curlHandle, CURLINFO_HTTP_CODE));
  369. $parts = explode("\r\n\r\n", $response);
  370. $responseBody = array_pop($parts);
  371. $responseHeader = array_pop($parts);
  372. $this->response->setHeaders($this->parseHeaders($responseHeader));
  373. curl_close($curlHandle);
  374. return $responseBody;
  375. }
  376. /**
  377. * Get the header info to store.
  378. *
  379. * @param string $header
  380. *
  381. * @return array
  382. */
  383. private function parseHeaders($header)
  384. {
  385. $headers = [];
  386. foreach (explode("\r\n", $header) as $line) {
  387. if (strpos($line, ':') !== false) {
  388. list ($key, $value) = explode(': ', $line);
  389. $key = str_replace('-', '_', strtolower($key));
  390. $headers[$key] = trim($value);
  391. }
  392. }
  393. return $headers;
  394. }
  395. /**
  396. * Encode application authorization header with base64.
  397. *
  398. * @param Consumer $consumer
  399. *
  400. * @return string
  401. */
  402. private function encodeAppAuthorization(Consumer $consumer)
  403. {
  404. $key = rawurlencode($consumer->key);
  405. $secret = rawurlencode($consumer->secret);
  406. return base64_encode($key . ':' . $secret);
  407. }
  408. }