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