GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#489)
by
unknown
04:21
created

TwitterOAuth::getUploadStatus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 7
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
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
9
use Abraham\TwitterOAuth\Util\JsonDecoder;
10
11
/**
12
 * TwitterOAuth class for interacting with the Twitter API.
13
 *
14
 * @author Abraham Williams <[email protected]>
15
 */
16
class TwitterOAuth extends Config
17
{
18
    const API_VERSION = '1.1';
19
    const API_HOST = 'https://api.twitter.com';
20
    const UPLOAD_HOST = 'https://upload.twitter.com';
21
    const UPLOAD_CHUNK = 40960; // 1024 * 40
22
23
    /** @var Response details about the result of the last request */
24
    private $response;
25
    /** @var string|null Application bearer token */
26
    private $bearer;
27
    /** @var Consumer Twitter application details */
28
    private $consumer;
29
    /** @var Token|null User access token details */
30
    private $token;
31
    /** @var HmacSha1 OAuth 1 signature type used by Twitter */
32
    private $signatureMethod;
33
34
    /**
35
     * Constructor
36
     *
37
     * @param string      $consumerKey      The Application Consumer Key
38
     * @param string      $consumerSecret   The Application Consumer Secret
39
     * @param string|null $oauthToken       The Client Token (optional)
40
     * @param string|null $oauthTokenSecret The Client Token Secret (optional)
41
     */
42
    public function __construct($consumerKey, $consumerSecret, $oauthToken = null, $oauthTokenSecret = null)
43
    {
44
        $this->resetLastResponse();
45
        $this->signatureMethod = new HmacSha1();
46
        $this->consumer = new Consumer($consumerKey, $consumerSecret);
47
        if (!empty($oauthToken) && !empty($oauthTokenSecret)) {
48
            $this->token = new Token($oauthToken, $oauthTokenSecret);
49
        }
50
        if (empty($oauthToken) && !empty($oauthTokenSecret)) {
51
            $this->bearer = $oauthTokenSecret;
52
        }
53
    }
54
55
    /**
56
     * @param string $oauthToken
57
     * @param string $oauthTokenSecret
58
     */
59
    public function setOauthToken($oauthToken, $oauthTokenSecret)
60
    {
61
        $this->token = new Token($oauthToken, $oauthTokenSecret);
62
    }
63
64
    /**
65
     * @return string|null
66
     */
67
    public function getLastApiPath()
68
    {
69
        return $this->response->getApiPath();
70
    }
71
72
    /**
73
     * @return int
74
     */
75
    public function getLastHttpCode()
76
    {
77
        return $this->response->getHttpCode();
78
    }
79
80
    /**
81
     * @return array
82
     */
83
    public function getLastXHeaders()
84
    {
85
        return $this->response->getXHeaders();
86
    }
87
88
    /**
89
     * @return array|object|null
90
     */
91
    public function getLastBody()
92
    {
93
        return $this->response->getBody();
94
    }
95
96
    /**
97
     * Resets the last response cache.
98
     */
99
    public function resetLastResponse()
100
    {
101
        $this->response = new Response();
102
    }
103
104
    /**
105
     * Make URLs for user browser navigation.
106
     *
107
     * @param string $path
108
     * @param array  $parameters
109
     *
110
     * @return string
111
     */
112
    public function url($path, array $parameters)
113
    {
114
        $this->resetLastResponse();
115
        $this->response->setApiPath($path);
116
        $query = http_build_query($parameters);
117
        return sprintf('%s/%s?%s', self::API_HOST, $path, $query);
118
    }
119
120
    /**
121
     * Make /oauth/* requests to the API.
122
     *
123
     * @param string $path
124
     * @param array  $parameters
125
     *
126
     * @return array
127
     * @throws TwitterOAuthException
128
     */
129
    public function oauth($path, array $parameters = [])
130
    {
131
        $response = [];
132
        $this->resetLastResponse();
133
        $this->response->setApiPath($path);
134
        $url = sprintf('%s/%s', self::API_HOST, $path);
135
        $result = $this->oAuthRequest($url, 'POST', $parameters);
136
137
        if ($this->getLastHttpCode() != 200) {
138
            throw new TwitterOAuthException($result);
139
        }
140
141
        parse_str($result, $response);
142
        $this->response->setBody($response);
0 ignored issues
show
Bug introduced by
It seems like $response can also be of type null; however, Abraham\TwitterOAuth\Response::setBody() does only seem to accept array|object, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
143
144
        return $response;
145
    }
146
147
    /**
148
     * Make /oauth2/* requests to the API.
149
     *
150
     * @param string $path
151
     * @param array  $parameters
152
     *
153
     * @return array|object
154
     */
155
    public function oauth2($path, array $parameters = [])
156
    {
157
        $method = 'POST';
158
        $this->resetLastResponse();
159
        $this->response->setApiPath($path);
160
        $url = sprintf('%s/%s', self::API_HOST, $path);
161
        $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
162
        $authorization = 'Authorization: Basic ' . $this->encodeAppAuthorization($this->consumer);
163
        $result = $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
164
        $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
165
        $this->response->setBody($response);
166
        return $response;
167
    }
168
169
    /**
170
     * Make GET requests to the API.
171
     *
172
     * @param string $path
173
     * @param array  $parameters
174
     *
175
     * @return array|object
176
     */
177
    public function get($path, array $parameters = [])
178
    {
179
        return $this->http('GET', self::API_HOST, $path, $parameters);
180
    }
181
182
    /**
183
     * Make POST requests to the API.
184
     *
185
     * @param string $path
186
     * @param array  $parameters
187
     *
188
     * @return array|object
189
     */
190
    public function post($path, array $parameters = [])
191
    {
192
        return $this->http('POST', self::API_HOST, $path, $parameters);
193
    }
194
195
    /**
196
     * Make DELETE requests to the API.
197
     *
198
     * @param string $path
199
     * @param array  $parameters
200
     *
201
     * @return array|object
202
     */
203
    public function delete($path, array $parameters = [])
204
    {
205
        return $this->http('DELETE', self::API_HOST, $path, $parameters);
206
    }
207
208
    /**
209
     * Make PUT requests to the API.
210
     *
211
     * @param string $path
212
     * @param array  $parameters
213
     *
214
     * @return array|object
215
     */
216
    public function put($path, array $parameters = [])
217
    {
218
        return $this->http('PUT', self::API_HOST, $path, $parameters);
219
    }
220
221
    /**
222
     * Upload media to upload.twitter.com.
223
     *
224
     * @param string $path
225
     * @param array  $parameters
226
     * @param boolean  $chunked
227
     *
228
     * @return array|object
229
     */
230
    public function upload($path, array $parameters = [], $chunked = false)
231
    {
232
        if ($chunked) {
233
            return $this->uploadMediaChunked($path, $parameters);
234
        } else {
235
            return $this->uploadMediaNotChunked($path, $parameters);
236
        }
237
    }
238
239
    /**
240
     * Private method to upload media (not chunked) to upload.twitter.com.
241
     *
242
     * @param string $path
243
     * @param array  $parameters
244
     *
245
     * @return array|object
246
     */
247
    private function uploadMediaNotChunked($path, array $parameters)
248
    {
249
        $file = file_get_contents($parameters['media']);
250
        $base = base64_encode($file);
251
        $parameters['media'] = $base;
252
        return $this->http('POST', self::UPLOAD_HOST, $path, $parameters);
253
    }
254
255
/**
256
     * Checks to see whether the upload  was successful or not
257
     *
258
     * @param $media_id
259
     * @return array|object
260
     */
261
    public function getUploadStatus($media_id)
262
    {
263
        return $this->http('GET', self::UPLOAD_HOST, 'media/upload', array(
264
            'command' => 'STATUS',
265
            'media_id' => $media_id,
266
        ));
267
    }
268
269
    /**
270
     * Private method to upload media (chunked) to upload.twitter.com.
271
     *
272
     * @param string $path
273
     * @param array  $parameters
274
     *
275
     * @return array|object
276
     */
277
    private function uploadMediaChunked($path, $parameters)
278
    {
279
        $arr = [
280
            'command' => 'INIT',
281
            'media_type' => $parameters['media_type'],
282
            'total_bytes' => filesize($parameters['media'])
283
        ];
284
285
        if (!empty($parameters['media_category'])) {
286
            $arr['media_category'] = $parameters['media_category']; //need for activate async
287
        }
288
289
        // Init
290
        $init = $this->http('POST', self::UPLOAD_HOST, $path, $arr);
291
        // Append
292
        $segment_index = 0;
293
        $media = fopen($parameters['media'], 'rb');
294
        while (!feof($media))
295
        {
296
            $this->http('POST', self::UPLOAD_HOST, 'media/upload', [
297
                'command' => 'APPEND',
298
                'media_id' => $init->media_id_string,
299
                'segment_index' => $segment_index++,
300
                'media_data' => base64_encode(fread($media, self::UPLOAD_CHUNK))
301
            ]);
302
        }
303
        fclose($media);
304
        // Finalize
305
        $finalize = $this->http('POST', self::UPLOAD_HOST, 'media/upload', [
306
            'command' => 'FINALIZE',
307
            'media_id' => $init->media_id_string
308
        ]);
309
        return $finalize;
310
    }
311
312
    /**
313
     * @param string $method
314
     * @param string $host
315
     * @param string $path
316
     * @param array  $parameters
317
     *
318
     * @return array|object
319
     */
320
    private function http($method, $host, $path, array $parameters)
321
    {
322
        $this->resetLastResponse();
323
        $url = sprintf('%s/%s/%s.json', $host, self::API_VERSION, $path);
324
        $this->response->setApiPath($path);
325
        $result = $this->oAuthRequest($url, $method, $parameters);
326
        $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
327
        $this->response->setBody($response);
328
        return $response;
329
    }
330
331
    /**
332
     * Format and sign an OAuth / API request
333
     *
334
     * @param string $url
335
     * @param string $method
336
     * @param array  $parameters
337
     *
338
     * @return string
339
     * @throws TwitterOAuthException
340
     */
341
    private function oAuthRequest($url, $method, array $parameters)
342
    {
343
        $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
344
        if (array_key_exists('oauth_callback', $parameters)) {
345
            // Twitter doesn't like oauth_callback as a parameter.
346
            unset($parameters['oauth_callback']);
347
        }
348
        if ($this->bearer === null) {
349
            $request->signRequest($this->signatureMethod, $this->consumer, $this->token);
350
            $authorization = $request->toHeader();
351
        } else {
352
            $authorization = 'Authorization: Bearer ' . $this->bearer;
353
        }
354
        return $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
355
    }
356
357
    /**
358
     * Make an HTTP request
359
     *
360
     * @param string $url
361
     * @param string $method
362
     * @param string $authorization
363
     * @param array $postfields
364
     *
365
     * @return string
366
     * @throws TwitterOAuthException
367
     */
368
    private function request($url, $method, $authorization, array $postfields)
369
    {
370
        /* Curl settings */
371
        $options = [
372
            // CURLOPT_VERBOSE => true,
373
            CURLOPT_CAINFO => __DIR__ . DIRECTORY_SEPARATOR . 'cacert.pem',
374
            CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
375
            CURLOPT_HEADER => true,
376
            CURLOPT_HTTPHEADER => ['Accept: application/json', $authorization, 'Expect:'],
377
            CURLOPT_RETURNTRANSFER => true,
378
            CURLOPT_SSL_VERIFYHOST => 2,
379
            CURLOPT_SSL_VERIFYPEER => true,
380
            CURLOPT_TIMEOUT => $this->timeout,
381
            CURLOPT_URL => $url,
382
            CURLOPT_USERAGENT => $this->userAgent,
383
        ];
384
385
        if($this->gzipEncoding) {
386
            $options[CURLOPT_ENCODING] = 'gzip';
387
        }
388
389
        if (!empty($this->proxy)) {
390
            $options[CURLOPT_PROXY] = $this->proxy['CURLOPT_PROXY'];
391
            $options[CURLOPT_PROXYUSERPWD] = $this->proxy['CURLOPT_PROXYUSERPWD'];
392
            $options[CURLOPT_PROXYPORT] = $this->proxy['CURLOPT_PROXYPORT'];
393
            $options[CURLOPT_PROXYAUTH] = CURLAUTH_BASIC;
394
            $options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP;
395
        }
396
397
        switch ($method) {
398
            case 'GET':
399
                break;
400
            case 'POST':
401
                $options[CURLOPT_POST] = true;
402
                $options[CURLOPT_POSTFIELDS] = Util::buildHttpQuery($postfields);
403
                break;
404
            case 'DELETE':
405
                $options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
406
                break;
407
            case 'PUT':
408
                $options[CURLOPT_CUSTOMREQUEST] = 'PUT';
409
                break;
410
        }
411
412
        if (in_array($method, ['GET', 'PUT', 'DELETE']) && !empty($postfields)) {
413
            $options[CURLOPT_URL] .= '?' . Util::buildHttpQuery($postfields);
414
        }
415
416
417
        $curlHandle = curl_init();
418
        curl_setopt_array($curlHandle, $options);
419
        $response = curl_exec($curlHandle);
420
421
        // Throw exceptions on cURL errors.
422
        if (curl_errno($curlHandle) > 0) {
423
            throw new TwitterOAuthException(curl_error($curlHandle), curl_errno($curlHandle));
424
        }
425
426
        $this->response->setHttpCode(curl_getinfo($curlHandle, CURLINFO_HTTP_CODE));
427
        $parts = explode("\r\n\r\n", $response);
428
        $responseBody = array_pop($parts);
429
        $responseHeader = array_pop($parts);
430
        $this->response->setHeaders($this->parseHeaders($responseHeader));
431
432
        curl_close($curlHandle);
433
434
        return $responseBody;
435
    }
436
437
    /**
438
     * Get the header info to store.
439
     *
440
     * @param string $header
441
     *
442
     * @return array
443
     */
444
    private function parseHeaders($header)
445
    {
446
        $headers = [];
447
        foreach (explode("\r\n", $header) as $line) {
448
            if (strpos($line, ':') !== false) {
449
                list ($key, $value) = explode(': ', $line);
450
                $key = str_replace('-', '_', strtolower($key));
451
                $headers[$key] = trim($value);
452
            }
453
        }
454
        return $headers;
455
    }
456
457
    /**
458
     * Encode application authorization header with base64.
459
     *
460
     * @param Consumer $consumer
461
     *
462
     * @return string
463
     */
464
    private function encodeAppAuthorization(Consumer $consumer)
465
    {
466
        $key = rawurlencode($consumer->key);
467
        $secret = rawurlencode($consumer->secret);
468
        return base64_encode($key . ':' . $secret);
469
    }
470
}
471