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.

CurlBuilder::hasErrors()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 0
cts 2
cp 0
rs 10
cc 1
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * Copyright 2015 Dirk Groenen
4
 *
5
 * (c) Dirk Groenen <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace DirkGroenen\Pinterest\Utils;
12
13
use DirkGroenen\Pinterest\Exceptions\PinterestException;
14
15
class CurlBuilder {
16
17
    /**
18
     * Contains the curl instance
19
     *
20
     * @var resource
21
     */
22
    private $curl;
23
24
    /**
25
     * Array containing headers from last performed request
26
     *
27
     * @var array
28
     */
29
    private $headers;
30
31
    /**
32
     * Constructor
33
     */
34 43
    public function __construct()
35
    {
36 43
        $this->curl = curl_init();
37 43
    }
38
39
    /**
40
     * Return a new instance of the CurlBuilder
41
     *
42
     * @access public
43
     * @return CurlBuilder
44
     */
45
    public function create()
46
    {
47
        return new self();
48
    }
49
50
    /**
51
     * Sets an option in the curl instance
52
     *
53
     * @access public
54
     * @param  string   $option
55
     * @param  false|string    $value
56
     * @return $this
57
     */
58
    public function setOption($option, $value)
59
    {
60
        curl_setopt($this->curl, $option, $value);
61
62
        return $this;
63
    }
64
65
    /**
66
     * Sets multiple options at the same time
67
     *
68
     * @access public
69
     * @param  array   $options
70
     * @return $this
71
     */
72
    public function setOptions(array $options = [])
73
    {
74
        curl_setopt_array($this->curl, $options);
75
76
        return $this;
77
    }
78
79
    /**
80
     * Execute the curl request
81
     *
82
     * @access public
83
     * @return false|string
84
     */
85
    public function execute()
86
    {
87
        return $this->execFollow();
88
    }
89
90
    /**
91
     * Check if the curl request ended up with errors
92
     *
93
     * @access public
94
     * @return integer
95
     */
96
    public function hasErrors()
97
    {
98
        return curl_errno($this->curl);
99
    }
100
101
    /**
102
     * Get curl errors
103
     *
104
     * @access public
105
     * @return string
106
     */
107
    public function getErrors()
108
    {
109
        return curl_error($this->curl);
110
    }
111
112
    /**
113
     * Get last curl error number
114
     *
115
     * @access public
116
     * @return int
117
     */
118
    public function getErrorNumber()
119
    {
120
        return curl_errno($this->curl);
121
    }
122
123
    /**
124
     * Get curl info key
125
     *
126
     * @access public
127
     * @param  string  $key
128
     * @return string
129
     */
130
    public function getInfo($key)
131
    {
132
        return curl_getinfo($this->curl, $key);
133
    }
134
135
    /**
136
     * Get headers
137
     *
138
     * @access public
139
     * @return string
140
     */
141
    public function getHeaders()
142
    {
143
        return $this->headers;
144
    }
145
146
    /**
147
     * Close the curl resource
148
     *
149
     * @access public
150
     * @return void
151
     */
152
    public function close()
153
    {
154
        curl_close($this->curl);
155
    }
156
157
    /**
158
     * Parse string headers into array
159
     *
160
     * @access private
161
     * @param string $headers
162
     * @return array
163
     */
164
    private function parseHeaders($headers) {
165
        $result = array();
166
        foreach (explode("\n", $headers) as $row) {
167
            $header = explode(':', $row, 2);
168
            if (count($header) == 2) {
169
                $result[$header[0]] = trim($header[1]);
170
            } else {
171
                $result[] = $header[0];
172
            }
173
        }
174
        return $result;
175
    }
176
177
    /**
178
     * Function which acts as a replacement for curl's default
179
     * FOLLOW_LOCATION option, since that gives errors when
180
     * combining it with open basedir.
181
     *
182
     * @see http://slopjong.de/2012/03/31/curl-follow-locations-with-safe_mode-enabled-or-open_basedir-set/
183
     * @access private
184
     * @return false|string
185
     */
186
    private function execFollow() {
187
        $mr = 5;
188
        $body = null;
189
190
        if (ini_get("open_basedir") == "" && ini_get("safe_mode" == "Off")) {
191
            $this->setOptions(array(
192
                CURLOPT_FOLLOWLOCATION => $mr > 0,
193
                CURLOPT_MAXREDIRS => $mr
194
            ));
195
        } else {
196
            $this->setOption(CURLOPT_FOLLOWLOCATION, false);
197
198
            if ($mr > 0) {
199
                $original_url = $this->getInfo(CURLINFO_EFFECTIVE_URL);
200
                $newurl = $original_url;
201
202
                $this->setOptions(array(
203
                    CURLOPT_HEADER => true,
204
                    CURLOPT_FORBID_REUSE => false
205
                ));
206
207
                do {
208
                    $this->setOption(CURLOPT_URL, $newurl);
209
210
                    $response = curl_exec($this->curl);
211
212
                    $header_size = $this->getInfo(CURLINFO_HEADER_SIZE);
213
                    $header = substr($response, 0, $header_size);
214
                    $body = substr($response, $header_size);
215
216
                    if ($this->getErrorNumber()) {
217
                        $code = 0;
218
                    } else {
219
                        $code = $this->getInfo(CURLINFO_HTTP_CODE);
220
221
                        if ($code == 301 || $code == 302 || $code == 308) {
222
                            preg_match('/Location:(.*?)\n/i', $header, $matches);
223
                            $newurl = trim(array_pop($matches));
224
                        } else if ($code >= 300 && $code <= 399) {
225
                            throw new PinterestException('Error: Unhandled 3xx HTTP code: ' . $code);
226
                        } else {
227
                            $code = 0;
228
                        }
229
                    }
230
                } while ($code && --$mr);
231
232
                if (!$mr) {
233
                    if ($mr === null) {
234
                        trigger_error('Too many redirects.', E_USER_WARNING);
235
                    }
236
237
                    return false;
238
                }
239
240
                $this->headers = $this->parseHeaders($header);
241
            }
242
        }
243
244
        if (!$body) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $body of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
245
            $this->setOption(CURLOPT_HEADER, true);
0 ignored issues
show
Documentation introduced by
true is of type boolean, but the function expects a false|string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
246
            $response = $this->execute();
247
248
            $header_size = $this->getInfo(CURLINFO_HEADER_SIZE);
249
            $header = substr($response, 0, $header_size);
250
            $body = substr($response, $header_size);
251
252
            $this->headers = $this->parseHeaders($header);
253
        }
254
255
        return $body;
256
    }
257
}