· 7 years ago · Mar 01, 2018, 09:26 PM
1<?php
2
3/**
4 * Twitter-API-PHP : Simple PHP wrapper for the v1.1 API
5 *
6 * PHP version 5.3.10
7 *
8 * @category Awesomeness
9 * @package Twitter-API-PHP
10 * @author James Mallison <me@j7mbo.co.uk>
11 * @license MIT License
12 * @version 1.0.4
13 * @link http://github.com/j7mbo/twitter-api-php
14 */
15class TwitterAPIExchange
16{
17 /**
18 * @var string
19 */
20 private $oauth_access_token;
21
22 /**
23 * @var string
24 */
25 private $oauth_access_token_secret;
26
27 /**
28 * @var string
29 */
30 private $consumer_key;
31
32 /**
33 * @var string
34 */
35 private $consumer_secret;
36
37 /**
38 * @var array
39 */
40 private $postfields;
41
42 /**
43 * @var string
44 */
45 private $getfield;
46
47 /**
48 * @var mixed
49 */
50 protected $oauth;
51
52 /**
53 * @var string
54 */
55 public $url;
56
57 /**
58 * @var string
59 */
60 public $requestMethod;
61
62 /**
63 * The HTTP status code from the previous request
64 *
65 * @var int
66 */
67 protected $httpStatusCode;
68
69 /**
70 * Create the API access object. Requires an array of settings::
71 * oauth access token, oauth access token secret, consumer key, consumer secret
72 * These are all available by creating your own application on dev.twitter.com
73 * Requires the cURL library
74 *
75 * @throws \RuntimeException When cURL isn't loaded
76 * @throws \InvalidArgumentException When incomplete settings parameters are provided
77 *
78 * @param array $settings
79 */
80 public function __construct(array $settings)
81 {
82 if (!function_exists('curl_init'))
83 {
84 throw new RuntimeException('TwitterAPIExchange requires cURL extension to be loaded, see: http://curl.haxx.se/docs/install.html');
85 }
86
87 if (!isset($settings['oauth_access_token'])
88 || !isset($settings['oauth_access_token_secret'])
89 || !isset($settings['consumer_key'])
90 || !isset($settings['consumer_secret']))
91 {
92 throw new InvalidArgumentException('Incomplete settings passed to TwitterAPIExchange');
93 }
94
95 $this->oauth_access_token = $settings['oauth_access_token'];
96 $this->oauth_access_token_secret = $settings['oauth_access_token_secret'];
97 $this->consumer_key = $settings['consumer_key'];
98 $this->consumer_secret = $settings['consumer_secret'];
99 }
100
101 /**
102 * Set postfields array, example: array('screen_name' => 'J7mbo')
103 *
104 * @param array $array Array of parameters to send to API
105 *
106 * @throws \Exception When you are trying to set both get and post fields
107 *
108 * @return TwitterAPIExchange Instance of self for method chaining
109 */
110 public function setPostfields(array $array)
111 {
112 if (!is_null($this->getGetfield()))
113 {
114 throw new Exception('You can only choose get OR post fields.');
115 }
116
117 if (isset($array['status']) && substr($array['status'], 0, 1) === '@')
118 {
119 $array['status'] = sprintf("\0%s", $array['status']);
120 }
121
122 foreach ($array as $key => &$value)
123 {
124 if (is_bool($value))
125 {
126 $value = ($value === true) ? 'true' : 'false';
127 }
128 }
129
130 $this->postfields = $array;
131
132 // rebuild oAuth
133 if (isset($this->oauth['oauth_signature'])) {
134 $this->buildOauth($this->url, $this->requestMethod);
135 }
136
137 return $this;
138 }
139
140 /**
141 * Set getfield string, example: '?screen_name=J7mbo'
142 *
143 * @param string $string Get key and value pairs as string
144 *
145 * @throws \Exception
146 *
147 * @return \TwitterAPIExchange Instance of self for method chaining
148 */
149 public function setGetfield($string)
150 {
151 if (!is_null($this->getPostfields()))
152 {
153 throw new Exception('You can only choose get OR post fields.');
154 }
155
156 $getfields = preg_replace('/^\?/', '', explode('&', $string));
157 $params = array();
158
159 foreach ($getfields as $field)
160 {
161 if ($field !== '')
162 {
163 list($key, $value) = explode('=', $field);
164 $params[$key] = $value;
165 }
166 }
167
168 $this->getfield = '?' . http_build_query($params);
169
170 return $this;
171 }
172
173 /**
174 * Get getfield string (simple getter)
175 *
176 * @return string $this->getfields
177 */
178 public function getGetfield()
179 {
180 return $this->getfield;
181 }
182
183 /**
184 * Get postfields array (simple getter)
185 *
186 * @return array $this->postfields
187 */
188 public function getPostfields()
189 {
190 return $this->postfields;
191 }
192
193 /**
194 * Build the Oauth object using params set in construct and additionals
195 * passed to this method. For v1.1, see: https://dev.twitter.com/docs/api/1.1
196 *
197 * @param string $url The API url to use. Example: https://api.twitter.com/1.1/search/tweets.json
198 * @param string $requestMethod Either POST or GET
199 *
200 * @throws \Exception
201 *
202 * @return \TwitterAPIExchange Instance of self for method chaining
203 */
204 public function buildOauth($url, $requestMethod)
205 {
206 if (!in_array(strtolower($requestMethod), array('post', 'get')))
207 {
208 throw new Exception('Request method must be either POST or GET');
209 }
210
211 $consumer_key = $this->consumer_key;
212 $consumer_secret = $this->consumer_secret;
213 $oauth_access_token = $this->oauth_access_token;
214 $oauth_access_token_secret = $this->oauth_access_token_secret;
215
216 $oauth = array(
217 'oauth_consumer_key' => $consumer_key,
218 'oauth_nonce' => time(),
219 'oauth_signature_method' => 'HMAC-SHA1',
220 'oauth_token' => $oauth_access_token,
221 'oauth_timestamp' => time(),
222 'oauth_version' => '1.0'
223 );
224
225 $getfield = $this->getGetfield();
226
227 if (!is_null($getfield))
228 {
229 $getfields = str_replace('?', '', explode('&', $getfield));
230
231 foreach ($getfields as $g)
232 {
233 $split = explode('=', $g);
234
235 /** In case a null is passed through **/
236 if (isset($split[1]))
237 {
238 $oauth[$split[0]] = urldecode($split[1]);
239 }
240 }
241 }
242
243 $postfields = $this->getPostfields();
244
245 if (!is_null($postfields)) {
246 foreach ($postfields as $key => $value) {
247 $oauth[$key] = $value;
248 }
249 }
250
251 $base_info = $this->buildBaseString($url, $requestMethod, $oauth);
252 $composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
253 $oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
254 $oauth['oauth_signature'] = $oauth_signature;
255
256 $this->url = $url;
257 $this->requestMethod = $requestMethod;
258 $this->oauth = $oauth;
259
260 return $this;
261 }
262
263 /**
264 * Perform the actual data retrieval from the API
265 *
266 * @param boolean $return If true, returns data. This is left in for backward compatibility reasons
267 * @param array $curlOptions Additional Curl options for this request
268 *
269 * @throws \Exception
270 *
271 * @return string json If $return param is true, returns json data.
272 */
273 public function performRequest($return = true, $curlOptions = array())
274 {
275 if (!is_bool($return))
276 {
277 throw new Exception('performRequest parameter must be true or false');
278 }
279
280 $header = array($this->buildAuthorizationHeader($this->oauth), 'Expect:');
281
282 $getfield = $this->getGetfield();
283 $postfields = $this->getPostfields();
284
285 $options = array(
286 CURLOPT_HTTPHEADER => $header,
287 CURLOPT_HEADER => false,
288 CURLOPT_URL => $this->url,
289 CURLOPT_RETURNTRANSFER => true,
290 CURLOPT_TIMEOUT => 10,
291 ) + $curlOptions;
292
293 if (!is_null($postfields))
294 {
295 $options[CURLOPT_POSTFIELDS] = http_build_query($postfields);
296 }
297 else
298 {
299 if ($getfield !== '')
300 {
301 $options[CURLOPT_URL] .= $getfield;
302 }
303 }
304
305 $feed = curl_init();
306 curl_setopt_array($feed, $options);
307 $json = curl_exec($feed);
308
309 $this->httpStatusCode = curl_getinfo($feed, CURLINFO_HTTP_CODE);
310
311 if (($error = curl_error($feed)) !== '')
312 {
313 curl_close($feed);
314
315 throw new \Exception($error);
316 }
317
318 curl_close($feed);
319
320 return $json;
321 }
322
323 /**
324 * Private method to generate the base string used by cURL
325 *
326 * @param string $baseURI
327 * @param string $method
328 * @param array $params
329 *
330 * @return string Built base string
331 */
332 private function buildBaseString($baseURI, $method, $params)
333 {
334 $return = array();
335 ksort($params);
336
337 foreach($params as $key => $value)
338 {
339 $return[] = rawurlencode($key) . '=' . rawurlencode($value);
340 }
341
342 return $method . "&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $return));
343 }
344
345 /**
346 * Private method to generate authorization header used by cURL
347 *
348 * @param array $oauth Array of oauth data generated by buildOauth()
349 *
350 * @return string $return Header used by cURL for request
351 */
352 private function buildAuthorizationHeader(array $oauth)
353 {
354 $return = 'Authorization: OAuth ';
355 $values = array();
356
357 foreach($oauth as $key => $value)
358 {
359 if (in_array($key, array('oauth_consumer_key', 'oauth_nonce', 'oauth_signature',
360 'oauth_signature_method', 'oauth_timestamp', 'oauth_token', 'oauth_version'))) {
361 $values[] = "$key=\"" . rawurlencode($value) . "\"";
362 }
363 }
364
365 $return .= implode(', ', $values);
366 return $return;
367 }
368
369 /**
370 * Helper method to perform our request
371 *
372 * @param string $url
373 * @param string $method
374 * @param string $data
375 * @param array $curlOptions
376 *
377 * @throws \Exception
378 *
379 * @return string The json response from the server
380 */
381 public function request($url, $method = 'get', $data = null, $curlOptions = array())
382 {
383 if (strtolower($method) === 'get')
384 {
385 $this->setGetfield($data);
386 }
387 else
388 {
389 $this->setPostfields($data);
390 }
391
392 return $this->buildOauth($url, $method)->performRequest(true, $curlOptions);
393 }
394
395 /**
396 * Get the HTTP status code for the previous request
397 *
398 * @return integer
399 */
400 public function getHttpStatusCode()
401 {
402 return $this->httpStatusCode;
403 }
404}