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  http://opensource.org/licenses/gpl-license.php GNU Public License
12 * @link     http://github.com/j7mbo/twitter-api-php
13 */
14class TwitterAPIExchange
15{
16    private $oauth_access_token;
17    private $oauth_access_token_secret;
18    private $consumer_key;
19    private $consumer_secret;
20    private $postfields;
21    private $getfield;
22    protected $oauth;
23    public $url;
24
25    /**
26     * Create the API access object. Requires an array of settings::
27     * oauth access token, oauth access token secret, consumer key, consumer secret
28     * These are all available by creating your own application on dev.twitter.com
29     * Requires the cURL library
30     *
31     * @param array $settings
32     */
33    public function __construct(array $settings)
34    {
35        if (!in_array('curl', get_loaded_extensions()))
36        {
37            throw new Exception('You need to install cURL, see: http://curl.haxx.se/docs/install.html');
38        }
39
40        if (!isset($settings['oauth_access_token'])
41            || !isset($settings['oauth_access_token_secret'])
42            || !isset($settings['consumer_key'])
43            || !isset($settings['consumer_secret']))
44        {
45            throw new Exception('Make sure you are passing in the correct parameters');
46        }
47
48        $this->oauth_access_token = $settings['oauth_access_token'];
49        $this->oauth_access_token_secret = $settings['oauth_access_token_secret'];
50        $this->consumer_key = $settings['consumer_key'];
51        $this->consumer_secret = $settings['consumer_secret'];
52    }
53
54    /**
55     * Set postfields array, example: array('screen_name' => 'J7mbo')
56     *
57     * @param array $array Array of parameters to send to API
58     *
59     * @return TwitterAPIExchange Instance of self for method chaining
60     */
61    public function setPostfields(array $array)
62    {
63        if (!is_null($this->getGetfield()))
64        {
65            throw new Exception('You can only choose get OR post fields.');
66        }
67
68        if (isset($array['status']) && substr($array['status'], 0, 1) === '@')
69        {
70            $array['status'] = sprintf("\0%s", $array['status']);
71        }
72
73        $this->postfields = $array;
74
75        return $this;
76    }
77
78    /**
79     * Set getfield string, example: '?screen_name=J7mbo'
80     *
81     * @param string $string Get key and value pairs as string
82     *
83     * @return \TwitterAPIExchange Instance of self for method chaining
84     */
85    public function setGetfield($string)
86    {
87        if (!is_null($this->getPostfields()))
88        {
89            throw new Exception('You can only choose get OR post fields.');
90        }
91
92        $search = array('#', ',', '+', ':');
93        $replace = array('%23', '%2C', '%2B', '%3A');
94        $string = str_replace($search, $replace, $string);
95
96        $this->getfield = $string;
97
98        return $this;
99    }
100
101    /**
102     * Get getfield string (simple getter)
103     *
104     * @return string $this->getfields
105     */
106    public function getGetfield()
107    {
108        return $this->getfield;
109    }
110
111    /**
112     * Get postfields array (simple getter)
113     *
114     * @return array $this->postfields
115     */
116    public function getPostfields()
117    {
118        return $this->postfields;
119    }
120
121    /**
122     * Build the Oauth object using params set in construct and additionals
123     * passed to this method. For v1.1, see: https://dev.twitter.com/docs/api/1.1
124     *
125     * @param string $url The API url to use. Example: https://api.twitter.com/1.1/search/tweets.json
126     * @param string $requestMethod Either POST or GET
127     * @return \TwitterAPIExchange Instance of self for method chaining
128     */
129    public function buildOauth($url, $requestMethod)
130    {
131        if (!in_array(strtolower($requestMethod), array('post', 'get')))
132        {
133            throw new Exception('Request method must be either POST or GET');
134        }
135
136        $consumer_key = $this->consumer_key;
137        $consumer_secret = $this->consumer_secret;
138        $oauth_access_token = $this->oauth_access_token;
139        $oauth_access_token_secret = $this->oauth_access_token_secret;
140
141        $oauth = array(
142            'oauth_consumer_key' => $consumer_key,
143            'oauth_nonce' => time(),
144            'oauth_signature_method' => 'HMAC-SHA1',
145            'oauth_token' => $oauth_access_token,
146            'oauth_timestamp' => time(),
147            'oauth_version' => '1.0'
148        );
149
150        $getfield = $this->getGetfield();
151
152        if (!is_null($getfield))
153        {
154            $getfields = str_replace('?', '', explode('&', $getfield));
155            foreach ($getfields as $g)
156            {
157                $split = explode('=', $g);
158                $oauth[$split[0]] = $split[1];
159            }
160        }
161
162        $base_info = $this->buildBaseString($url, $requestMethod, $oauth);
163        $composite_key = rawurlencode($consumer_secret) . '&' . rawurlencode($oauth_access_token_secret);
164        $oauth_signature = base64_encode(hash_hmac('sha1', $base_info, $composite_key, true));
165        $oauth['oauth_signature'] = $oauth_signature;
166
167        $this->url = $url;
168        $this->oauth = $oauth;
169
170        return $this;
171    }
172
173    /**
174     * Perform the actual data retrieval from the API
175     *
176     * @param boolean $return If true, returns data.
177     *
178     * @return string json If $return param is true, returns json data.
179     */
180    public function performRequest($return = true)
181    {
182        if (!is_bool($return))
183        {
184            throw new Exception('performRequest parameter must be true or false');
185        }
186
187        $header = array($this->buildAuthorizationHeader($this->oauth), 'Expect:');
188
189        $getfield = $this->getGetfield();
190        $postfields = $this->getPostfields();
191
192        $options = array(
193            CURLOPT_HTTPHEADER => $header,
194            CURLOPT_HEADER => false,
195            CURLOPT_URL => $this->url,
196            CURLOPT_RETURNTRANSFER => true
197        );
198
199        if (!is_null($postfields))
200        {
201            $options[CURLOPT_POSTFIELDS] = $postfields;
202        }
203        else
204        {
205            if ($getfield !== '')
206            {
207                $options[CURLOPT_URL] .= $getfield;
208            }
209        }
210
211        $feed = curl_init();
212        curl_setopt_array($feed, $options);
213        $json = curl_exec($feed);
214        curl_close($feed);
215
216        if ($return) { return $json; }
217    }
218
219    /**
220     * Private method to generate the base string used by cURL
221     *
222     * @param string $baseURI
223     * @param string $method
224     * @param array $params
225     *
226     * @return string Built base string
227     */
228    private function buildBaseString($baseURI, $method, $params)
229    {
230        $return = array();
231        ksort($params);
232
233        foreach($params as $key=>$value)
234        {
235            $return[] = "$key=" . $value;
236        }
237
238        return $method . "&" . rawurlencode($baseURI) . '&' . rawurlencode(implode('&', $return));
239    }
240
241    /**
242     * Private method to generate authorization header used by cURL
243     *
244     * @param array $oauth Array of oauth data generated by buildOauth()
245     *
246     * @return string $return Header used by cURL for request
247     */
248    private function buildAuthorizationHeader($oauth)
249    {
250        $return = 'Authorization: OAuth ';
251        $values = array();
252
253        foreach($oauth as $key => $value)
254        {
255            $values[] = "$key=\"" . rawurlencode($value) . "\"";
256        }
257
258        $return .= implode(', ', $values);
259        return $return;
260    }
261
262}
263