Completed
Push — master ( adc61b...88ab02 )
by Hector
03:43
created

TwitterAds::manageErrors()   C

Complexity

Conditions 8
Paths 8

Size

Total Lines 22
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 19
nc 8
nop 1
dl 0
loc 22
rs 6.6037
c 0
b 0
f 0
1
<?php
2
3
namespace Hborras\TwitterAdsSDK;
4
5
use Exception;
6
use Hborras\TwitterAdsSDK\TwitterAds\Account;
7
use Hborras\TwitterAdsSDK;
8
use Hborras\TwitterAdsSDK\TwitterAds\Cursor;
9
use Hborras\TwitterAdsSDK\TwitterAds\Errors\BadRequest;
10
use Hborras\TwitterAdsSDK\TwitterAds\Errors\Forbidden;
11
use Hborras\TwitterAdsSDK\TwitterAds\Errors\NotAuthorized;
12
use Hborras\TwitterAdsSDK\TwitterAds\Errors\NotFound;
13
use Hborras\TwitterAdsSDK\TwitterAds\Errors\RateLimit;
14
use Hborras\TwitterAdsSDK\TwitterAds\Errors\ServerError;
15
use Hborras\TwitterAdsSDK\TwitterAds\Errors\ServiceUnavailable;
16
use Hborras\TwitterAdsSDK\Util\JsonDecoder;
17
18
/**
19
 * TwitterAds class for interacting with the Twitter API.
20
 *
21
 * @author Hector Borras <[email protected]>
22
 */
23
class TwitterAds extends Config
24
{
25
    const API_VERSION      = '1';
26
    const API_REST_VERSION = '1.1';
27
    const API_HOST         = 'https://ads-api.twitter.com';
28
    const API_HOST_SANDBOX = 'https://ads-api-sandbox.twitter.com';
29
    const API_HOST_OAUTH   = 'https://api.twitter.com';
30
    const UPLOAD_HOST      = 'https://upload.twitter.com';
31
    const UPLOAD_PATH      = 'media/upload.json';
32
    const UPLOAD_CHUNK     = 40960; // 1024 * 40
33
34
    /** @var TwitterAds */
35
    protected static $instance;
36
    /** @var  string Method used for the request */
37
    private $method;
38
    /** @var  string Resource used for the request */
39
    private $resource;
40
    /** @var Response details about the result of the last request */
41
    private $response;
42
    /** @var string|null Application bearer token */
43
    private $bearer;
44
    /** @var Consumer Twitter application details */
45
    private $consumer;
46
    /** @var Token|null User access token details */
47
    private $token;
48
    /** @var HmacSha1 OAuth 1 signature type used by Twitter */
49
    private $signatureMethod;
50
    /** @var  bool Sandbox allows to make requests thought sandbox environment */
51
    private $sandbox;
52
    /** @var string */
53
    private $accountId;
54
55
    /**
56
     * @return TwitterAds|null
57
     */
58
    public static function instance()
59
    {
60
        return static::$instance;
61
    }
62
63
    /**
64
     * @param TwitterAds $instance
65
     */
66
    public static function setInstance(TwitterAds $instance)
67
    {
68
        static::$instance = $instance;
69
    }
70
71
    /**
72
     * Constructor.
73
     *
74
     * @param string $consumerKey The Application Consumer Key
75
     * @param string $consumerSecret The Application Consumer Secret
76
     * @param string|null $oauthToken The Client Token
77
     * @param string|null $oauthTokenSecret The Client Token Secret
78
     * @param string $accountId
79
     * @param bool $sandbox The Sandbox environment (optional)
80
     */
81
    public function __construct($consumerKey, $consumerSecret, $oauthToken = '', $oauthTokenSecret = '', $accountId = '', $sandbox = false)
82
    {
83
        $this->resetLastResponse();
84
        $this->signatureMethod = new HmacSha1();
85
        $this->consumer = new Consumer($consumerKey, $consumerSecret);
86
        if (!empty($oauthToken) && !empty($oauthTokenSecret)) {
87
            $this->token = new Token($oauthToken, $oauthTokenSecret);
88
        }
89
        if (empty($oauthToken) && !empty($oauthTokenSecret)) {
90
            $this->bearer = $oauthTokenSecret;
91
        }
92
        $this->sandbox = $sandbox;
93
        $this->accountId = $accountId;
94
    }
95
96
    /**
97
     * @param $consumerKey
98
     * @param $consumerSecret
99
     * @param $oauthToken
100
     * @param $oauthTokenSecret
101
     * @param string $accountId
102
     * @param bool $sandbox
103
     * @return static
104
     */
105
    public static function init($consumerKey, $consumerSecret, $oauthToken = '', $oauthTokenSecret = '', $accountId = '', $sandbox = false)
106
    {
107
108
        $api = new static($consumerKey, $consumerSecret, $oauthToken, $oauthTokenSecret, $accountId, $sandbox);
109
        static::setInstance($api);
110
111
        return $api;
112
    }
113
114
    /**
115
     * @return Account|Cursor
116
     */
117
    public function getAccounts()
118
    {
119
        return (new Account($this))->all();
120
    }
121
122
    /**
123
     * @param string $oauthToken
124
     * @param string $oauthTokenSecret
125
     */
126
    public function setOauthToken($oauthToken, $oauthTokenSecret)
127
    {
128
        $this->token = new Token($oauthToken, $oauthTokenSecret);
129
    }
130
131
    /**
132
     * @return string|null
133
     */
134
    public function getLastApiPath()
135
    {
136
        return $this->response->getApiPath();
137
    }
138
139
    /**
140
     * @return int
141
     */
142
    public function getLastHttpCode()
143
    {
144
        return $this->response->getHttpCode();
145
    }
146
147
    /**
148
     * @return array
149
     */
150
    public function getLastXHeaders()
151
    {
152
        return $this->response->getXHeaders();
153
    }
154
155
    /**
156
     * @return array|object|null
157
     */
158
    public function getLastBody()
159
    {
160
        return $this->response->getBody();
161
    }
162
163
    /**
164
     * Resets the last response cache.
165
     */
166
    public function resetLastResponse()
167
    {
168
        $this->response = new Response();
169
    }
170
171
    /**
172
     * Make URLs for user browser navigation.
173
     *
174
     * @param string $path
175
     * @param array $parameters
176
     *
177
     * @return string
178
     */
179
    public function url($path, array $parameters)
180
    {
181
        $this->resetLastResponse();
182
        $this->response->setApiPath($path);
183
        $query = http_build_query($parameters);
184
185
        return sprintf('%s/%s?%s', self::API_HOST_OAUTH, $path, $query);
186
    }
187
188
    /**
189
     * Make /oauth/* requests to the API.
190
     *
191
     * @param string $path
192
     * @param array $parameters
193
     * @return array
194
     * @throws Exception
195
     */
196
    public function oauth($path, array $parameters = [])
197
    {
198
        $response = [];
199
        $this->resetLastResponse();
200
        $this->response->setApiPath($path);
201
        $url = sprintf('%s/%s', self::API_HOST_OAUTH, $path);
202
        $result = $this->oAuthRequest($url, 'POST', $parameters);
203
204
        if ($this->getLastHttpCode() != 200) {
205
            throw new TwitterAdsException($result, 500, null, $result);
206
        }
207
208
        parse_str($result, $response);
209
        $this->response->setBody($response);
210
211
        return $response;
212
    }
213
214
    /**
215
     * Make /oauth2/* requests to the API.
216
     *
217
     * @param string $path
218
     * @param array $parameters
219
     *
220
     * @return array|object
221
     */
222
    public function oauth2($path, array $parameters = [])
223
    {
224
        $method = 'POST';
225
        $this->resetLastResponse();
226
        $this->response->setApiPath($path);
227
        $url = sprintf('%s/%s', self::API_HOST_OAUTH, $path);
228
        $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
229
        $authorization = 'Authorization: Basic ' . $this->encodeAppAuthorization($this->consumer);
230
        $result = $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters);
231
        $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
232
        $this->response->setBody($response);
233
234
        return $response;
235
    }
236
237
    public function verifyCredentials($parameters = [])
238
    {
239
        return $this->http('GET', self::API_HOST_OAUTH, 'account/verify_credentials', $parameters);
240
    }
241
242
    /**
243
     * Make GET requests to the API.
244
     *
245
     * @param string $path
246
     * @param array $parameters
247
     *
248
     * @return Response
249
     */
250
    public function get($path, array $parameters = [])
251
    {
252
        return $this->http('GET', !$this->sandbox ? self::API_HOST : self::API_HOST_SANDBOX, $path, $parameters);
253
    }
254
255
    /**
256
     * Make POST requests to the API.
257
     *
258
     * @param string $path
259
     * @param array $parameters
260
     *
261
     * @param array $headers
262
     * @return Response
263
     */
264
    public function post($path, array $parameters = [], array $headers = [])
265
    {
266
        return $this->http('POST', !$this->sandbox ? self::API_HOST : self::API_HOST_SANDBOX, $path, $parameters, $headers);
267
    }
268
269
    /**
270
     * Make DELETE requests to the API.
271
     *
272
     * @param string $path
273
     * @param array $parameters
274
     *
275
     * @return Response
276
     */
277
    public function delete($path, array $parameters = [])
278
    {
279
        return $this->http('DELETE', !$this->sandbox ? self::API_HOST : self::API_HOST_SANDBOX, $path, $parameters);
280
    }
281
282
    /**
283
     * Make PUT requests to the API.
284
     *
285
     * @param string $path
286
     * @param array $parameters
287
     *
288
     * @return Response
289
     */
290
    public function put($path, array $parameters = [], array $headers = [])
291
    {
292
        return $this->http('PUT', !$this->sandbox ? self::API_HOST : self::API_HOST_SANDBOX, $path, $parameters, $headers);
293
    }
294
295
    /**
296
     * Upload media to upload.twitter.com.
297
     *
298
     * @param array $parameters
299
     * @param bool $chunked
300
     *
301
     * @return array|object
302
     */
303
    public function upload(array $parameters = [], $chunked = false)
304
    {
305
        if ($chunked) {
306
            return $this->uploadMediaChunked(self::UPLOAD_PATH, $parameters);
307
        } else {
308
            return $this->uploadMediaNotChunked(self::UPLOAD_PATH, $parameters)->getBody();
309
        }
310
    }
311
312
    /**
313
     * Private method to upload media (not chunked) to upload.twitter.com.
314
     *
315
     * @param string $path
316
     * @param array $parameters
317
     *
318
     * @return array|object
319
     */
320
    private function uploadMediaNotChunked($path, $parameters)
321
    {
322
        $file = file_get_contents($parameters['media']);
323
        $base = base64_encode($file);
324
        $parameters['media'] = $base;
325
326
        return $this->http('POST', self::UPLOAD_HOST, $path, $parameters);
327
    }
328
329
    /**
330
     * Private method to upload media (chunked) to upload.twitter.com.
331
     *
332
     * @param string $path
333
     * @param array $parameters
334
     *
335
     * @return array|object
336
     */
337
    private function uploadMediaChunked($path, $parameters)
338
    {
339
        if ($parameters['media_type'] == 'video/mp4') {
340
            $parameters['media_category'] = "amplify_video";
341
        } elseif ($parameters['media_type'] == 'image/gif') {
342
            $parameters['media_category'] = 'tweet_gif';
343
        } else {
344
            $parameters['media_category'] = 'tweet_image';
345
        }
346
347
        // Init
348
        $initParameters = [
349
            'command' => 'INIT',
350
            'media_type' => $parameters['media_type'],
351
            'media_category' => $parameters['media_category'],
352
            'total_bytes' => filesize($parameters['media'])
353
        ];
354
355
        if (isset($parameters['additional_owners']) && is_array($parameters['additional_owners'])) {
356
            $initParameters['additional_owners'] = implode(',', $parameters['additional_owners']);
357
        }
358
359
        $init = $this->http(
360
            'POST',
361
            self::UPLOAD_HOST,
362
            $path,
363
            $initParameters
364
        )->getBody();
365
366
        // Append
367
        $segment_index = 0;
368
        $media = fopen($parameters['media'], 'rb');
369
        while (!feof($media)) {
370
            $this->http(
0 ignored issues
show
Unused Code introduced by
The call to the method Hborras\TwitterAdsSDK\Response::getBody() seems un-needed as the method has no side-effects.

PHP Analyzer performs a side-effects analysis of your code. A side-effect is basically anything that might be visible after the scope of the method is left.

Let’s take a look at an example:

class User
{
    private $email;

    public function getEmail()
    {
        return $this->email;
    }

    public function setEmail($email)
    {
        $this->email = $email;
    }
}

If we look at the getEmail() method, we can see that it has no side-effect. Whether you call this method or not, no future calls to other methods are affected by this. As such code as the following is useless:

$user = new User();
$user->getEmail(); // This line could safely be removed as it has no effect.

On the hand, if we look at the setEmail(), this method _has_ side-effects. In the following case, we could not remove the method call:

$user = new User();
$user->setEmail('email@domain'); // This line has a side-effect (it changes an
                                 // instance variable).
Loading history...
371
                'POST',
372
                self::UPLOAD_HOST,
373
                $path,
374
                [
375
                    'command' => 'APPEND',
376
                    'media_id' => $init->media_id_string,
377
                    'segment_index' => $segment_index++,
378
                    'media_data' => base64_encode(fread($media, self::UPLOAD_CHUNK)),
379
                ]
380
            )->getBody();
381
        }
382
        fclose($media);
383
        // Finalize
384
        $finalize = $this->http(
385
            'POST',
386
            self::UPLOAD_HOST,
387
            $path,
388
            [
389
                'command' => 'FINALIZE',
390
                'media_id' => $init->media_id_string,
391
            ]
392
        )->getBody();
393
394
        while (isset($finalize->processing_info)) {
395
            if (isset($finalize->processing_info->check_after_secs)) {
396
                sleep($finalize->processing_info->check_after_secs);
397
                $data = array(
398
                    'command' => 'STATUS',
399
                    'media_id' => $finalize->media_id
400
                );
401
                $finalize = $this->http('GET', self::UPLOAD_HOST, $path, $data)->getBody();
402
            } else {
403
                if (isset($finalize->processing_info->state) && $finalize->processing_info->state == 'succeeded') {
404
                    break;
405
                }
406
            }
407
        }
408
409
        return $finalize;
410
    }
411
412
    /**
413
     * @param string $method
414
     * @param string $host
415
     * @param string $path
416
     * @param array $parameters
417
     * @param array $headers
418
     * @return Response
419
     * @throws BadRequest
420
     * @throws Forbidden
421
     * @throws NotAuthorized
422
     * @throws NotFound
423
     * @throws RateLimit
424
     * @throws ServerError
425
     * @throws ServiceUnavailable
426
     */
427
    private function http($method, $host, $path, array $parameters, $headers = [])
428
    {
429
        $this->method = $method;
430
        $this->resource = $path;
431
        $this->resetLastResponse();
432
        if (strpos($path, TONUpload::DEFAULT_DOMAIN) === 0) {
433
            $url = $path;
434
        } else {
435
            if ($host == self::UPLOAD_HOST) {
436
                $url = sprintf('%s/%s/%s', $host, self::API_REST_VERSION, $path);
437
            } else {
438
                $url = sprintf('%s/%s/%s', $host, self::API_VERSION, $path);
439
            }
440
        }
441
442
        $this->response->setApiPath($path);
443
        $result = $this->oAuthRequest($url, $method, $parameters, $headers);
444
        $response = JsonDecoder::decode($result, $this->decodeJsonAsArray);
445
        $this->response->setBody($response);
446
        if ($this->getLastHttpCode() > 399) {
447
            $this->manageErrors($response);
448
        }
449
        return $this->response;
450
    }
451
452
    /**
453
     * @param $response
454
     * @throws BadRequest
455
     * @throws Forbidden
456
     * @throws NotAuthorized
457
     * @throws NotFound
458
     * @throws RateLimit
459
     * @throws ServerError
460
     * @throws ServiceUnavailable
461
     */
462
    public function manageErrors($response)
463
    {
464
        switch ($this->getLastHttpCode()) {
465
            case 400:
466
                throw new BadRequest(TwitterAdsException::BAD_REQUEST, 400, null, $response->errors);
467
            case 401:
468
                throw new NotAuthorized(TwitterAdsException::NOT_AUTHORIZED, 401, null, $response->errors);
469
            case 403:
470
                throw new Forbidden(TwitterAdsException::FORBIDDEN, 403, null, $response->errors);
471
            case 404:
472
                throw new NotFound(TwitterAdsException::NOT_FOUND, 404, null, $response->errors);
473
            case 429:
474
                throw new RateLimit(TwitterAdsException::RATE_LIMIT, 429, null, $response->errors, $this->response->getsHeaders());
475
            case 500:
476
                throw new ServerError(TwitterAdsException::SERVER_ERROR, 500, null, $response->errors);
477
            case 503:
478
                throw new ServiceUnavailable(TwitterAdsException::SERVICE_UNAVAILABLE, 503, null, $response->errors, $this->response->getsHeaders());
479
            default:
480
                print_r($response->errors);
481
                throw new ServerError(TwitterAdsException::SERVER_ERROR, 500, null, $response->errors);
482
        }
483
    }
484
485
    /**
486
     * Format and sign an OAuth / API request.
487
     *
488
     * @param string $url
489
     * @param string $method
490
     * @param array $parameters
491
     *
492
     * @param array $headers
493
     * @return string
494
     * @throws TwitterAdsException
495
     */
496
    private function oAuthRequest($url, $method, array $parameters, $headers = [])
497
    {
498
        $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
499
        if (array_key_exists('oauth_callback', $parameters)) {
500
            // Twitter doesn't like oauth_callback as a parameter.
501
            unset($parameters['oauth_callback']);
502
        }
503
        if ($this->bearer === null) {
504
            $request->signRequest($this->signatureMethod, $this->consumer, $this->token);
505
            $authorization = $request->toHeader();
506
        } else {
507
            $authorization = 'Authorization: Bearer ' . $this->bearer;
508
        }
509
        if (strpos($url, TONUpload::DEFAULT_DOMAIN) === 0) {
510
            return $this->request($url, $method, $authorization, $parameters, $headers);
511
        } else {
512
            return $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters, $headers);
513
        }
514
515
    }
516
517
    /**
518
     * Make an HTTP request.
519
     *
520
     * @param string $url
521
     * @param string $method
522
     * @param string $authorization
523
     * @param array $postfields
524
     *
525
     * @param array $headers
526
     * @return string
527
     * @throws TwitterAdsException
528
     */
529
    private function request($url, $method, $authorization, $postfields, $headers = [])
530
    {
531
        /* Curl settings */
532
        $options = [
533
            CURLOPT_VERBOSE => false,
534
            CURLOPT_CAINFO => __DIR__ . DIRECTORY_SEPARATOR . 'cacert.pem',
535
            CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
536
            CURLOPT_HEADER => true,
537
            CURLOPT_HTTPHEADER => array_merge(['Accept: */*', $authorization, 'Expect:'], $headers, ['Connection: close']),
538
            CURLOPT_RETURNTRANSFER => true,
539
            CURLOPT_SSL_VERIFYHOST => 2,
540
            CURLOPT_SSL_VERIFYPEER => true,
541
            CURLOPT_TIMEOUT => $this->timeout,
542
            CURLOPT_URL => $url,
543
            CURLOPT_USERAGENT => $this->userAgent,
544
            CURLOPT_ENCODING => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
545
        ];
546
547
        if (!empty($this->proxy)) {
548
            $options[CURLOPT_PROXY] = $this->proxy['CURLOPT_PROXY'];
549
            $options[CURLOPT_PROXYUSERPWD] = $this->proxy['CURLOPT_PROXYUSERPWD'];
550
            $options[CURLOPT_PROXYPORT] = $this->proxy['CURLOPT_PROXYPORT'];
551
            $options[CURLOPT_PROXYAUTH] = CURLAUTH_BASIC;
552
            $options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP;
553
        }
554
555
        switch ($method) {
556
            case 'GET':
557
                break;
558
            case 'POST':
559
                $options[CURLOPT_POST] = true;
560
                if (isset($postfields['raw'])) {
561
                    $options[CURLOPT_POSTFIELDS] = $postfields['raw'];
562
                } else {
563
                    $options[CURLOPT_POSTFIELDS] = Util::buildHttpQuery($postfields);
564
                }
565
566
                break;
567
            case 'DELETE':
568
                $options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
569
                break;
570
            case 'PUT':
571
                $options[CURLOPT_CUSTOMREQUEST] = 'PUT';
572
                if (isset($postfields['raw'])) {
573
                    $options[CURLOPT_POSTFIELDS] = $postfields['raw'];
574
                }
575
                break;
576
        }
577
578
        if (in_array($method, ['GET', 'PUT', 'DELETE']) && !empty($postfields) && !isset($postfields['raw'])) {
579
            $options[CURLOPT_URL] .= '?' . Util::buildHttpQuery($postfields);
580
        }
581
582
        $curlHandle = curl_init();
583
        curl_setopt_array($curlHandle, $options);
584
        $response = curl_exec($curlHandle);
585
        // Throw exceptions on cURL errors.
586
        if (curl_errno($curlHandle) > 0) {
587
            throw new TwitterAdsException(curl_error($curlHandle), curl_errno($curlHandle), null, null);
588
        }
589
        $this->response->setHttpCode(curl_getinfo($curlHandle, CURLINFO_HTTP_CODE));
590
        $parts = explode("\r\n\r\n", $response);
591
        $responseBody = array_pop($parts);
592
        $responseHeader = array_pop($parts);
593
        $this->response->setHeaders($this->parseHeaders($responseHeader));
594
        curl_close($curlHandle);
595
        return $responseBody;
596
    }
597
598
    /**
599
     * Get the header info to store.
600
     *
601
     * @param string $header
602
     *
603
     * @return array
604
     */
605
    private function parseHeaders($header)
606
    {
607
        $headers = [];
608
        foreach (explode("\r\n", $header) as $line) {
609
            if (strpos($line, ':') !== false) {
610
                list($key, $value) = explode(': ', $line);
611
                $key = str_replace('-', '_', strtolower($key));
612
                $headers[$key] = trim($value);
613
            }
614
        }
615
616
        return $headers;
617
    }
618
619
    /**
620
     * Set API URLS.
621
     */
622
    public function accessTokenURL()
623
    {
624
        return 'https://api.twitter.com/oauth/access_token';
625
    }
626
627
    public function authenticateURL()
628
    {
629
        return 'https://api.twitter.com/oauth/authenticate';
630
    }
631
632
    public function authorizeURL()
633
    {
634
        return 'https://api.twitter.com/oauth/authorize';
635
    }
636
637
    public function requestTokenURL()
638
    {
639
        return 'https://api.twitter.com/oauth/request_token';
640
    }
641
642
    /**
643
     * Encode application authorization header with base64.
644
     *
645
     * @param Consumer $consumer
646
     *
647
     * @return string
648
     */
649
    private function encodeAppAuthorization($consumer)
650
    {
651
        // TODO: key and secret should be rfc 1738 encoded
652
        $key = $consumer->key;
653
        $secret = $consumer->secret;
654
655
        return base64_encode($key . ':' . $secret);
656
    }
657
658
    /**
659
     * Return current response. Allows inheritance.
660
     *
661
     * @return Response
662
     */
663
    public function getResponse()
664
    {
665
        return $this->response;
666
    }
667
668
    /**
669
     * @return string
670
     */
671
    public function getMethod()
672
    {
673
        return $this->method;
674
    }
675
676
    /**
677
     * @return string
678
     */
679
    public function getResource()
680
    {
681
        return $this->resource;
682
    }
683
684
    /**
685
     * @return string
686
     */
687
    public function getAccountId()
688
    {
689
        return $this->accountId;
690
    }
691
692
    /**
693
     * @param string $accountId
694
     */
695
    public function setAccountId($accountId)
696
    {
697
        $this->accountId = $accountId;
698
    }
699
700 View Code Duplication
    public function getRequestToken($oauth_callback)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
701
    {
702
        $parameters = array();
703
        $parameters['oauth_callback'] = $oauth_callback;
704
        $request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters);
705
        $token = self::parse_parameters($request);
706
707
        return $token;
708
    }
709
710
    /**
711
     * Exchange request token and secret for an access token and
712
     * secret, to sign API calls.
713
     *
714
     * @param $oauth_verifier
715
     * @return array ("oauth_token" => "the-access-token",
716
     *                "oauth_token_secret" => "the-access-secret",
717
     * "user_id" => "9436992",
718
     * "screen_name" => "abraham")
719
     */
720 View Code Duplication
    public function getAccessToken($oauth_verifier)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
721
    {
722
        $parameters = array();
723
        $parameters['oauth_verifier'] = $oauth_verifier;
724
        $request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters);
725
        $token = self::parse_parameters($request);
726
727
        return $token;
728
    }
729
730
    // This function takes a input like a=b&a=c&d=e and returns the parsed
731
    // parameters like this
732
    // array('a' => array('b','c'), 'd' => 'e')
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
733 View Code Duplication
    public static function parse_parameters($input)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
734
    {
735
        if (!isset($input) || !$input) {
736
            return array();
737
        }
738
739
        $pairs = explode('&', $input);
740
741
        $parsed_parameters = array();
742
        foreach ($pairs as $pair) {
743
            $split = explode('=', $pair, 2);
744
            $parameter = self::urldecode_rfc3986($split[0]);
745
            $value = isset($split[1]) ? self::urldecode_rfc3986($split[1]) : '';
746
747
            if (isset($parsed_parameters[$parameter])) {
748
                // We have already recieved parameter(s) with this name, so add to the list
749
                // of parameters with this name
750
751
                if (is_scalar($parsed_parameters[$parameter])) {
752
                    // This is the first duplicate, so transform scalar (string) into an array
753
                    // so we can add the duplicates
754
                    $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]);
755
                }
756
757
                $parsed_parameters[$parameter][] = $value;
758
            } else {
759
                $parsed_parameters[$parameter] = $value;
760
            }
761
        }
762
763
        return $parsed_parameters;
764
    }
765
766
    public static function urlencode_rfc3986($input)
767
    {
768
        if (is_array($input)) {
769
            return array_map(array(__CLASS__, 'urlencode_rfc3986'), $input);
770
        } elseif (is_scalar($input)) {
771
            return str_replace(
772
                '',
773
                ' ',
774
                str_replace('%7E', '~', rawurlencode($input))
775
            );
776
        } else {
777
            return '';
778
        }
779
    }
780
781
    // This decode function isn't taking into consideration the above
782
    // modifications to the encoding process. However, this method doesn't
783
    // seem to be used anywhere so leaving it as is.
784
    public static function urldecode_rfc3986($string)
785
    {
786
        return urldecode($string);
787
    }
788
789
    /**
790
     * Get the authorize URL.
791
     *
792
     * @param $token
793
     * @param bool $sign_in_with_twitter
794
     * @return string
795
     */
796
    public function getAuthorizeURL($token, $sign_in_with_twitter = true)
797
    {
798
        if (is_array($token)) {
799
            $token = $token['oauth_token'];
800
        }
801
        if (empty($sign_in_with_twitter)) {
802
            return $this->authorizeURL() . "?oauth_token={$token}";
803
        } else {
804
            return $this->authenticateURL() . "?oauth_token={$token}";
805
        }
806
    }
807
}
808