Completed
Push — master ( 88ab02...5c5f74 )
by Hector
03:08 queued 01:23
created

TwitterAds::manageErrors()   B

Complexity

Conditions 8
Paths 8

Size

Total Lines 21
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 8
eloc 18
nc 8
nop 1
dl 0
loc 21
rs 7.1428
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
                throw new ServerError(TwitterAdsException::SERVER_ERROR, 500, null, $response->errors);
481
        }
482
    }
483
484
    /**
485
     * Format and sign an OAuth / API request.
486
     *
487
     * @param string $url
488
     * @param string $method
489
     * @param array $parameters
490
     *
491
     * @param array $headers
492
     * @return string
493
     * @throws TwitterAdsException
494
     */
495
    private function oAuthRequest($url, $method, array $parameters, $headers = [])
496
    {
497
        $request = Request::fromConsumerAndToken($this->consumer, $this->token, $method, $url, $parameters);
498
        if (array_key_exists('oauth_callback', $parameters)) {
499
            // Twitter doesn't like oauth_callback as a parameter.
500
            unset($parameters['oauth_callback']);
501
        }
502
        if ($this->bearer === null) {
503
            $request->signRequest($this->signatureMethod, $this->consumer, $this->token);
504
            $authorization = $request->toHeader();
505
        } else {
506
            $authorization = 'Authorization: Bearer ' . $this->bearer;
507
        }
508
        if (strpos($url, TONUpload::DEFAULT_DOMAIN) === 0) {
509
            return $this->request($url, $method, $authorization, $parameters, $headers);
510
        } else {
511
            return $this->request($request->getNormalizedHttpUrl(), $method, $authorization, $parameters, $headers);
512
        }
513
514
    }
515
516
    /**
517
     * Make an HTTP request.
518
     *
519
     * @param string $url
520
     * @param string $method
521
     * @param string $authorization
522
     * @param array $postfields
523
     *
524
     * @param array $headers
525
     * @return string
526
     * @throws TwitterAdsException
527
     */
528
    private function request($url, $method, $authorization, $postfields, $headers = [])
529
    {
530
        /* Curl settings */
531
        $options = [
532
            CURLOPT_VERBOSE => false,
533
            CURLOPT_CAINFO => __DIR__ . DIRECTORY_SEPARATOR . 'cacert.pem',
534
            CURLOPT_CONNECTTIMEOUT => $this->connectionTimeout,
535
            CURLOPT_HEADER => true,
536
            CURLOPT_HTTPHEADER => array_merge(['Accept: */*', $authorization, 'Expect:'], $headers, ['Connection: close']),
537
            CURLOPT_RETURNTRANSFER => true,
538
            CURLOPT_SSL_VERIFYHOST => 2,
539
            CURLOPT_SSL_VERIFYPEER => true,
540
            CURLOPT_TIMEOUT => $this->timeout,
541
            CURLOPT_URL => $url,
542
            CURLOPT_USERAGENT => $this->userAgent,
543
            CURLOPT_ENCODING => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
544
        ];
545
546
        if (!empty($this->proxy)) {
547
            $options[CURLOPT_PROXY] = $this->proxy['CURLOPT_PROXY'];
548
            $options[CURLOPT_PROXYUSERPWD] = $this->proxy['CURLOPT_PROXYUSERPWD'];
549
            $options[CURLOPT_PROXYPORT] = $this->proxy['CURLOPT_PROXYPORT'];
550
            $options[CURLOPT_PROXYAUTH] = CURLAUTH_BASIC;
551
            $options[CURLOPT_PROXYTYPE] = CURLPROXY_HTTP;
552
        }
553
554
        switch ($method) {
555
            case 'GET':
556
                break;
557
            case 'POST':
558
                $options[CURLOPT_POST] = true;
559
                if (isset($postfields['raw'])) {
560
                    $options[CURLOPT_POSTFIELDS] = $postfields['raw'];
561
                } else {
562
                    $options[CURLOPT_POSTFIELDS] = Util::buildHttpQuery($postfields);
563
                }
564
565
                break;
566
            case 'DELETE':
567
                $options[CURLOPT_CUSTOMREQUEST] = 'DELETE';
568
                break;
569
            case 'PUT':
570
                $options[CURLOPT_CUSTOMREQUEST] = 'PUT';
571
                if (isset($postfields['raw'])) {
572
                    $options[CURLOPT_POSTFIELDS] = $postfields['raw'];
573
                }
574
                break;
575
        }
576
577
        if (in_array($method, ['GET', 'PUT', 'DELETE']) && !empty($postfields) && !isset($postfields['raw'])) {
578
            $options[CURLOPT_URL] .= '?' . Util::buildHttpQuery($postfields);
579
        }
580
581
        $curlHandle = curl_init();
582
        curl_setopt_array($curlHandle, $options);
583
        $response = curl_exec($curlHandle);
584
        // Throw exceptions on cURL errors.
585
        if (curl_errno($curlHandle) > 0) {
586
            throw new TwitterAdsException(curl_error($curlHandle), curl_errno($curlHandle), null, null);
587
        }
588
        $this->response->setHttpCode(curl_getinfo($curlHandle, CURLINFO_HTTP_CODE));
589
        $parts = explode("\r\n\r\n", $response);
590
        $responseBody = array_pop($parts);
591
        $responseHeader = array_pop($parts);
592
        $this->response->setHeaders($this->parseHeaders($responseHeader));
593
        curl_close($curlHandle);
594
        return $responseBody;
595
    }
596
597
    /**
598
     * Get the header info to store.
599
     *
600
     * @param string $header
601
     *
602
     * @return array
603
     */
604
    private function parseHeaders($header)
605
    {
606
        $headers = [];
607
        foreach (explode("\r\n", $header) as $line) {
608
            if (strpos($line, ':') !== false) {
609
                list($key, $value) = explode(': ', $line);
610
                $key = str_replace('-', '_', strtolower($key));
611
                $headers[$key] = trim($value);
612
            }
613
        }
614
615
        return $headers;
616
    }
617
618
    /**
619
     * Set API URLS.
620
     */
621
    public function accessTokenURL()
622
    {
623
        return 'https://api.twitter.com/oauth/access_token';
624
    }
625
626
    public function authenticateURL()
627
    {
628
        return 'https://api.twitter.com/oauth/authenticate';
629
    }
630
631
    public function authorizeURL()
632
    {
633
        return 'https://api.twitter.com/oauth/authorize';
634
    }
635
636
    public function requestTokenURL()
637
    {
638
        return 'https://api.twitter.com/oauth/request_token';
639
    }
640
641
    /**
642
     * Encode application authorization header with base64.
643
     *
644
     * @param Consumer $consumer
645
     *
646
     * @return string
647
     */
648
    private function encodeAppAuthorization($consumer)
649
    {
650
        // TODO: key and secret should be rfc 1738 encoded
651
        $key = $consumer->key;
652
        $secret = $consumer->secret;
653
654
        return base64_encode($key . ':' . $secret);
655
    }
656
657
    /**
658
     * Return current response. Allows inheritance.
659
     *
660
     * @return Response
661
     */
662
    public function getResponse()
663
    {
664
        return $this->response;
665
    }
666
667
    /**
668
     * @return string
669
     */
670
    public function getMethod()
671
    {
672
        return $this->method;
673
    }
674
675
    /**
676
     * @return string
677
     */
678
    public function getResource()
679
    {
680
        return $this->resource;
681
    }
682
683
    /**
684
     * @return string
685
     */
686
    public function getAccountId()
687
    {
688
        return $this->accountId;
689
    }
690
691
    /**
692
     * @param string $accountId
693
     */
694
    public function setAccountId($accountId)
695
    {
696
        $this->accountId = $accountId;
697
    }
698
699 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...
700
    {
701
        $parameters = array();
702
        $parameters['oauth_callback'] = $oauth_callback;
703
        $request = $this->oAuthRequest($this->requestTokenURL(), 'GET', $parameters);
704
        $token = self::parse_parameters($request);
705
706
        return $token;
707
    }
708
709
    /**
710
     * Exchange request token and secret for an access token and
711
     * secret, to sign API calls.
712
     *
713
     * @param $oauth_verifier
714
     * @return array ("oauth_token" => "the-access-token",
715
     *                "oauth_token_secret" => "the-access-secret",
716
     * "user_id" => "9436992",
717
     * "screen_name" => "abraham")
718
     */
719 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...
720
    {
721
        $parameters = array();
722
        $parameters['oauth_verifier'] = $oauth_verifier;
723
        $request = $this->oAuthRequest($this->accessTokenURL(), 'GET', $parameters);
724
        $token = self::parse_parameters($request);
725
726
        return $token;
727
    }
728
729
    // This function takes a input like a=b&a=c&d=e and returns the parsed
730
    // parameters like this
731
    // 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...
732 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...
733
    {
734
        if (!isset($input) || !$input) {
735
            return array();
736
        }
737
738
        $pairs = explode('&', $input);
739
740
        $parsed_parameters = array();
741
        foreach ($pairs as $pair) {
742
            $split = explode('=', $pair, 2);
743
            $parameter = self::urldecode_rfc3986($split[0]);
744
            $value = isset($split[1]) ? self::urldecode_rfc3986($split[1]) : '';
745
746
            if (isset($parsed_parameters[$parameter])) {
747
                // We have already recieved parameter(s) with this name, so add to the list
748
                // of parameters with this name
749
750
                if (is_scalar($parsed_parameters[$parameter])) {
751
                    // This is the first duplicate, so transform scalar (string) into an array
752
                    // so we can add the duplicates
753
                    $parsed_parameters[$parameter] = array($parsed_parameters[$parameter]);
754
                }
755
756
                $parsed_parameters[$parameter][] = $value;
757
            } else {
758
                $parsed_parameters[$parameter] = $value;
759
            }
760
        }
761
762
        return $parsed_parameters;
763
    }
764
765
    public static function urlencode_rfc3986($input)
766
    {
767
        if (is_array($input)) {
768
            return array_map(array(__CLASS__, 'urlencode_rfc3986'), $input);
769
        } elseif (is_scalar($input)) {
770
            return str_replace(
771
                '',
772
                ' ',
773
                str_replace('%7E', '~', rawurlencode($input))
774
            );
775
        } else {
776
            return '';
777
        }
778
    }
779
780
    // This decode function isn't taking into consideration the above
781
    // modifications to the encoding process. However, this method doesn't
782
    // seem to be used anywhere so leaving it as is.
783
    public static function urldecode_rfc3986($string)
784
    {
785
        return urldecode($string);
786
    }
787
788
    /**
789
     * Get the authorize URL.
790
     *
791
     * @param $token
792
     * @param bool $sign_in_with_twitter
793
     * @return string
794
     */
795
    public function getAuthorizeURL($token, $sign_in_with_twitter = true)
796
    {
797
        if (is_array($token)) {
798
            $token = $token['oauth_token'];
799
        }
800
        if (empty($sign_in_with_twitter)) {
801
            return $this->authorizeURL() . "?oauth_token={$token}";
802
        } else {
803
            return $this->authenticateURL() . "?oauth_token={$token}";
804
        }
805
    }
806
}
807