Yaffs site version 1.1
[yaffs-website] / vendor / j7mbo / twitter-api-php / TwitterAPIExchange.php
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  */
15 class 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 (post fields include put).');
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         {
135             $this->buildOauth($this->url, $this->requestMethod);
136         }
137
138         return $this;
139     }
140
141     /**
142      * Set getfield string, example: '?screen_name=J7mbo'
143      *
144      * @param string $string Get key and value pairs as string
145      *
146      * @throws \Exception
147      *
148      * @return \TwitterAPIExchange Instance of self for method chaining
149      */
150     public function setGetfield($string)
151     {
152         if (!is_null($this->getPostfields()))
153         {
154             throw new Exception('You can only choose get OR post / post fields.');
155         }
156
157         $getfields = preg_replace('/^\?/', '', explode('&', $string));
158         $params = array();
159
160         foreach ($getfields as $field)
161         {
162             if ($field !== '')
163             {
164                 list($key, $value) = explode('=', $field);
165                 $params[$key] = $value;
166             }
167         }
168
169         $this->getfield = '?' . http_build_query($params, '', '&');
170
171         return $this;
172     }
173
174     /**
175      * Get getfield string (simple getter)
176      *
177      * @return string $this->getfields
178      */
179     public function getGetfield()
180     {
181         return $this->getfield;
182     }
183
184     /**
185      * Get postfields array (simple getter)
186      *
187      * @return array $this->postfields
188      */
189     public function getPostfields()
190     {
191         return $this->postfields;
192     }
193
194     /**
195      * Build the Oauth object using params set in construct and additionals
196      * passed to this method. For v1.1, see: https://dev.twitter.com/docs/api/1.1
197      *
198      * @param string $url           The API url to use. Example: https://api.twitter.com/1.1/search/tweets.json
199      * @param string $requestMethod Either POST or GET
200      *
201      * @throws \Exception
202      *
203      * @return \TwitterAPIExchange Instance of self for method chaining
204      */
205     public function buildOauth($url, $requestMethod)
206     {
207         if (!in_array(strtolower($requestMethod), array('post', 'get', 'put', 'delete')))
208         {
209             throw new Exception('Request method must be either POST, GET or PUT or DELETE');
210         }
211
212         $consumer_key              = $this->consumer_key;
213         $consumer_secret           = $this->consumer_secret;
214         $oauth_access_token        = $this->oauth_access_token;
215         $oauth_access_token_secret = $this->oauth_access_token_secret;
216
217         $oauth = array(
218             'oauth_consumer_key' => $consumer_key,
219             'oauth_nonce' => time(),
220             'oauth_signature_method' => 'HMAC-SHA1',
221             'oauth_token' => $oauth_access_token,
222             'oauth_timestamp' => time(),
223             'oauth_version' => '1.0'
224         );
225
226         $getfield = $this->getGetfield();
227
228         if (!is_null($getfield))
229         {
230             $getfields = str_replace('?', '', explode('&', $getfield));
231
232             foreach ($getfields as $g)
233             {
234                 $split = explode('=', $g);
235
236                 /** In case a null is passed through **/
237                 if (isset($split[1]))
238                 {
239                     $oauth[$split[0]] = urldecode($split[1]);
240                 }
241             }
242         }
243
244         $postfields = $this->getPostfields();
245
246         if (!is_null($postfields)) {
247             foreach ($postfields as $key => $value) {
248                 $oauth[$key] = $value;
249             }
250         }
251
252         $base_info = $this->buildBaseString($url, $requestMethod, $oauth);
253         $composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
254         $oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
255         $oauth['oauth_signature'] = $oauth_signature;
256
257         $this->url           = $url;
258         $this->requestMethod = $requestMethod;
259         $this->oauth         = $oauth;
260
261         return $this;
262     }
263
264     /**
265      * Perform the actual data retrieval from the API
266      *
267      * @param boolean $return      If true, returns data. This is left in for backward compatibility reasons
268      * @param array   $curlOptions Additional Curl options for this request
269      *
270      * @throws \Exception
271      *
272      * @return string json If $return param is true, returns json data.
273      */
274     public function performRequest($return = true, $curlOptions = array())
275     {
276         if (!is_bool($return))
277         {
278             throw new Exception('performRequest parameter must be true or false');
279         }
280
281         $header =  array($this->buildAuthorizationHeader($this->oauth), 'Expect:');
282
283         $getfield = $this->getGetfield();
284         $postfields = $this->getPostfields();
285
286         if (in_array(strtolower($this->requestMethod), array('put', 'delete')))
287         {
288             $curlOptions[CURLOPT_CUSTOMREQUEST] = $this->requestMethod;
289         }
290
291         $options = $curlOptions + array(
292             CURLOPT_HTTPHEADER => $header,
293             CURLOPT_HEADER => false,
294             CURLOPT_URL => $this->url,
295             CURLOPT_RETURNTRANSFER => true,
296             CURLOPT_TIMEOUT => 10,
297         );
298
299         if (!is_null($postfields))
300         {
301             $options[CURLOPT_POSTFIELDS] = http_build_query($postfields, '', '&');
302         }
303         else
304         {
305             if ($getfield !== '')
306             {
307                 $options[CURLOPT_URL] .= $getfield;
308             }
309         }
310
311         $feed = curl_init();
312         curl_setopt_array($feed, $options);
313         $json = curl_exec($feed);
314
315         $this->httpStatusCode = curl_getinfo($feed, CURLINFO_HTTP_CODE);
316
317         if (($error = curl_error($feed)) !== '')
318         {
319             curl_close($feed);
320
321             throw new \Exception($error);
322         }
323
324         curl_close($feed);
325
326         return $json;
327     }
328
329     /**
330      * Private method to generate the base string used by cURL
331      *
332      * @param string $baseURI
333      * @param string $method
334      * @param array  $params
335      *
336      * @return string Built base string
337      */
338     private function buildBaseString($baseURI, $method, $params)
339     {
340         $return = array();
341         ksort($params);
342
343         foreach($params as $key => $value)
344         {
345             $return[] = rawurlencode($key) . '=' . rawurlencode($value);
346         }
347
348         return $method . "&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $return));
349     }
350
351     /**
352      * Private method to generate authorization header used by cURL
353      *
354      * @param array $oauth Array of oauth data generated by buildOauth()
355      *
356      * @return string $return Header used by cURL for request
357      */
358     private function buildAuthorizationHeader(array $oauth)
359     {
360         $return = 'Authorization: OAuth ';
361         $values = array();
362
363         foreach($oauth as $key => $value)
364         {
365             if (in_array($key, array('oauth_consumer_key', 'oauth_nonce', 'oauth_signature',
366                 'oauth_signature_method', 'oauth_timestamp', 'oauth_token', 'oauth_version'))) {
367                 $values[] = "$key=\"" . rawurlencode($value) . "\"";
368             }
369         }
370
371         $return .= implode(', ', $values);
372         return $return;
373     }
374
375     /**
376      * Helper method to perform our request
377      *
378      * @param string $url
379      * @param string $method
380      * @param string $data
381      * @param array  $curlOptions
382      *
383      * @throws \Exception
384      *
385      * @return string The json response from the server
386      */
387     public function request($url, $method = 'get', $data = null, $curlOptions = array())
388     {
389         if (strtolower($method) === 'get')
390         {
391             $this->setGetfield($data);
392         }
393         else
394         {
395             $this->setPostfields($data);
396         }
397
398         return $this->buildOauth($url, $method)->performRequest(true, $curlOptions);
399     }
400
401     /**
402      * Get the HTTP status code for the previous request
403      *
404      * @return integer
405      */
406     public function getHttpStatusCode()
407     {
408         return $this->httpStatusCode;
409     }
410 }