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.
Test Failed
Push — master ( eabd30...25a381 )
by sunsky
02:14
created

Request::body()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 9
c 0
b 0
f 0
ccs 3
cts 3
cp 1
rs 9.6666
cc 1
eloc 4
nc 1
nop 2
crap 1
1
<?php
2
/**
3
 *
4
 * @author  [email protected] [email protected]
5
 * Date: 2017/6/16
6
 * Time: 10:02
7
 * @version $Id: $
8
 * @since 1.0
9
 * @copyright Sina Corp.
10
 */
11
12
namespace MultiHttp;
13
14
use MultiHttp\Exception\InvalidArgumentException;
15
16
class Request extends Http
17
{
18
    const MAX_REDIRECTS_DEFAULT = 10;
19
    protected static $curlAlias = array(
20
        'url' => 'CURLOPT_URL',
21
        'uri' => 'CURLOPT_URL',
22
        'debug' => 'CURLOPT_VERBOSE',//for debug verbose
23
        'method' => 'CURLOPT_CUSTOMREQUEST',
24
        'data' => 'CURLOPT_POSTFIELDS', // array or string , file begin with '@'
25
        'ua' => 'CURLOPT_USERAGENT',
26
        'timeout' => 'CURLOPT_TIMEOUT', // (secs) 0 means indefinitely
27
        'connect_timeout' => 'CURLOPT_CONNECTTIMEOUT',
28
        'referer' => 'CURLOPT_REFERER',
29
        'binary' => 'CURLOPT_BINARYTRANSFER',
30
        'port' => 'CURLOPT_PORT',
31
        'header' => 'CURLOPT_HEADER', // TRUE:include header
32
        'headers' => 'CURLOPT_HTTPHEADER', // array
33
        'download' => 'CURLOPT_FILE', // writing file stream (using fopen()), default is STDOUT
34
        'upload' => 'CURLOPT_INFILE', // reading file stream
35
        'transfer' => 'CURLOPT_RETURNTRANSFER', // TRUE:return string; FALSE:output directly (curl_exec)
36
        'follow_location' => 'CURLOPT_FOLLOWLOCATION',
37
        'timeout_ms' => 'CURLOPT_TIMEOUT_MS', // milliseconds,  libcurl version > 7.36.0 ,
38
    );
39
    protected static $logger;
40
    public $curlHandle;
41
    public
42
        $uri,
0 ignored issues
show
Coding Style introduced by
It is generally advisable to only define one property per statement.

Only declaring a single property per statement allows you to later on add doc comments more easily.

It is also recommended by PSR2, so it is a common style that many people expect.

Loading history...
Coding Style introduced by
The visibility should be declared for property $uri.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
43
        $timeout,
44
        $maxRedirects,
45
        $followRedirects;
46
    public $cert;
47
    public $key;
48
    public $passphrase;
49
    public $encoding;
50
    public $payload;
51
    protected $options = array(
52
        'CURLOPT_MAXREDIRS' => 10,
53
        'header' => true,
54
        'method' => self::GET,
55
        'transfer' => true,
56
        'follow_location' => true,
57
        'timeout' => 0);
58
    protected $endCallback;
59
    protected $withURIQuery;
60
    protected $hasInitialized = false;
61
62
    protected function __construct()
63
    {
64
65
    }
66
67
    public static function create()
68
    {
69
        return new self;
70
    }
71
72
    public static function setLogger($logger)
73
    {
74
        self::$logger = $logger;
75
    }
76
77
    /**
78
     * Specify   timeout
79
     * @param float|int $timeout seconds to timeout the HTTP call
80
     * @return Request
81
     */
82
    public function timeout($timeout)
83 2
    {
84
        $this->timeout = $timeout;
85 2
        return $this;
86
    }
87
88
    public function noFollow()
89
    {
90 2
        return $this->follow(0);
91
    }
92 2
93
    /**
94
     * If the response is a 301 or 302 redirect, automatically
95
     * send off another request to that location
96
     * @param int $follow follow or not to follow or maximal number of redirects
97
     * @return Request
98 1
     */
99
    public function follow(int $follow)
100 1
    {
101 1
        $this->maxRedirects = abs($follow);
102
        $this->followRedirects = $follow > 0;
103
        return $this;
104
    }
105
106
    public function endCallback()
107 2
    {
108
        return $this->endCallback;
109 2
    }
110 2
111 2
    public function hasEndCallback()
112 2
    {
113 2
        return isset($this->endCallback);
114 2
    }
115 2
116 2
    public function uri($uri)
117 2
    {
118 2
        $this->uri = $uri;
119
        return $this;
120
    }
121
122
    public function hasCert()
123
    {
124
        return isset($this->cert) && isset($this->key);
125 2
    }
126
127 2
    /**
128 2
     * Use Client Side Cert Authentication
129
     * @param string $key file path to client key
130
     * @param string $cert file path to client cert
131
     * @param string $passphrase for client key
132
     * @param string $encoding default PEM
133
     * @return Request
134
     */
135 2
    public function cert($cert, $key, $passphrase = null, $encoding = 'PEM')
136
    {
137 2
        $this->cert = $cert;
138 2
        $this->key = $key;
139 2
        $this->passphrase = $passphrase;
140
        $this->encoding = $encoding;
141
        return $this;
142
    }
143
144
    public function body($payload, $mimeType = null)
145
    {
146
        $this->mime($mimeType);
147 2
        $this->payload = $payload;
148
        // Iserntentially don't call _serializePayload yet.  Wait until
149 2
        // we actually send off the request to convert payload to string.
150 2
        // At that time, the `serialized_payload` is set accordingly.
151
        return $this;
152
    }
153
    public function mime($mime)
154
    {
155
        if (empty($mime)) return $this;
156
        $this->content_type = $this->expected_type = Mime::getFullMime($mime);
0 ignored issues
show
Bug introduced by
The property content_type does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
Bug introduced by
The property expected_type does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
157
        if ($this->isUpload()) {
0 ignored issues
show
Bug introduced by
The method isUpload() does not seem to exist on object<MultiHttp\Request>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
158
            $this->neverSerializePayload();
0 ignored issues
show
Bug introduced by
The method neverSerializePayload() does not seem to exist on object<MultiHttp\Request>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
159
        }
160
        return $this;
161
    }
162
    public function addHeader($header_name, $value)
163
    {
164
        $this->headers[$header_name] = $value;
0 ignored issues
show
Bug introduced by
The property headers does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
165
        return $this;
166
    }
167
168
    public function addHeaders(array $headers)
169
    {
170
        foreach ($headers as $header => $value) {
171
            $this->addHeader($header, $value);
172
        }
173
        return $this;
174
    }
175
    public function expectsType($mime)
176
    {
177 1
        return $this->expects($mime);
178
    }
179 1
    public function sendType($mime)
180 1
    {
181 1
        return $this->contentType = $mime;
0 ignored issues
show
Bug introduced by
The property contentType does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
182 1
    }
183
    public function expects($mime)
184
    {
185
        if (empty($mime)) return $this;
186
        $this->expected_type = Mime::getFullMime($mime);
187
        return $this;
188
    }
189
    /**
190
     * @param $field alias or field name
191
     * @return bool|mixed
192
     */
193
    public function getIni($field)
194
    {
195
        $alias = self::optionAlias($field);
196 2
        return isset($this->options[$alias]) ? $this->options[$alias] : false;
197
    }
198 2
199
    /**
200
     * @param $key
201
     * @return mixed
202
     */
203
    protected static function optionAlias($key)
204
    {
205 2
        $alias = false;
206
        if (isset(self::$curlAlias[$key])) {
207 2
            $alias = self::$curlAlias[$key];
208 2
        } elseif ((substr($key, 0, strlen('CURLOPT_')) == 'CURLOPT_') && defined($key)) {
209 2
            $alias = $key;
210
        }
211
        return $alias;
212
    }
213
214
    public function addQuery($data)
215
    {
216 2
        if (!empty($data)) {
217
            if (is_array($data)) {
218 2
                $this->withURIQuery = http_build_query($data);
219 2
            } else if (is_string($data)) {
220 2
                $this->withURIQuery = $data;
221 2
            } else {
222 2
                throw new InvalidArgumentException('data must be array or string');
223 2
            }
224 2
        }
225
        return $this;
226
    }
227
228
    public function post($uri, $payload = null, array $options = array())
229
    {
230
        return $this->ini(Http::POST, $uri, $payload, $options);
231 1
    }
232
233 1
    /*  no body  */
234 1
235 1 View Code Duplication
    protected function ini($method, $url,  $data , array $options = array())
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...
236 1
    {
237 1
        $options = array('url' => $url, 'method' => $method, 'data' => $data) + $options;
238 1
        $this->addOptions($options);
239
240
        return $this;
241 1
    }
242 1
243
    public function addOptions(array $options = array())
244
    {
245
        $this->options = $options + $this->options;
246
        $this->uri = $this->options['url'];
247
        return $this;
248
    }
249
250
    function put($uri, $payload = null, array $options = array())
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
251 1
    {
252
        return $this->ini(Http::PUT, $uri, $payload, $options);
253 1
    }
254
255
    function patch($uri, $payload = null, array $options = array())
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
256
    {
257
        return $this->ini(Http::PATCH, $uri, $payload, $options);
258
    }
259
260
    public function get($uri, array $options = array())
261
    {
262
        return $this->ini(Http::GET, $uri, array(), $options);
263 2
    }
264
265 2
    function options($uri, array $options = array())
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
266 2
    {
267
        return $this->ini(Http::OPTIONS, $uri, array(), $options);
268 2
    }
269
270
    function head($uri, array $options = array())
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
271
    {
272
        return $this->ini(Http::HEAD, $uri, array('CURLOPT_NOBODY' => true), $options);
273
    }
274
275 2
    function delete($uri, array $options = array())
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
276
    {
277 2
        return $this->ini(Http::DELETE, $uri, array(), $options);
278 2
    }
279 2
280
    function trace($uri, array $options = array())
0 ignored issues
show
Best Practice introduced by
It is generally recommended to explicitly declare the visibility for methods.

Adding explicit visibility (private, protected, or public) is generally recommend to communicate to other developers how, and from where this method is intended to be used.

Loading history...
281
    {
282
        return $this->ini(Http::TRACE, $uri, array(), $options);
283
    }
284
285
    /**
286
     * @return Response
287
     */
288 1
    public function send()
289
    {
290 1
        if (!$this->hasInitialized)
291
            $this->applyOptions();
292
        $response = $this->makeResponse();
293
        if ($this->endCallback) {
294
            $func = $this->endCallback;
295
            $func($response);
296
        }
297
        return $response;
298
    }
299 1
300
    public function applyOptions()
301 1
    {
302
        $curl = curl_init();
303
        $this->curlHandle = $curl;
304
        $this->prepare();
305
        $this->hasInitialized = true;
306
        return $this;
307
    }
308
309 1
    protected function prepare()
310
    {
311 1
        if (empty($this->options['url'])) {
312
            throw new InvalidArgumentException('url can not empty');
313
        }
314
315
        if (isset($this->options['data'])) {
316
            $this->options['data'] = is_array($this->options['data']) ? http_build_query($this->options['data']) : $this->options['data'];//for better compatibility
317
        }
318
        if (isset($this->withURIQuery)) {
319 1
            $this->options['url'] .= strpos($this->options['url'], '?') === FALSE ? '?' : '&';
320
            $this->options['url'] .= $this->withURIQuery;
321 1
        }
322
        if (isset($this->options['callback'])) {
323
            $this->onEnd($this->options['callback']);
324
            unset($this->options['callback']);
325
        }
326
        //swap ip and host
327
        if (!empty($this->options['ip'])) {
328
            $matches = array();
329 1
            preg_match('/\/\/([^\/]+)/', $this->options['url'], $matches);
330
            $host = $matches[1];
331 1
            if (empty($this->options['headers']) || !is_array($this->options['headers'])) {
332
                $this->options['headers'] = array('Host: ' . $host);
333
            } else {
334
                $this->options['headers'][] = 'Host: ' . $host;
335
            }
336
            $this->options['url'] = preg_replace('/\/\/([^\/]+)/', '//' . $this->options['ip'], $this->options['url']);
337
            unset($this->options['ip']);
338
            unset($host);
339 1
        }
340
        //process version
341 1
        if (!empty($this->options['http_version'])) {
342
            $version = $this->options['http_version'];
343
            if ($version == '1.0') {
344
                $this->options['CURLOPT_HTTP_VERSION'] = CURLOPT_HTTP_VERSION_1_0;
345
            } elseif ($version == '1.1') {
346
                $this->options['CURLOPT_HTTP_VERSION'] = CURLOPT_HTTP_VERSION_1_1;
347
            }
348
349 2
            unset($version);
350
        }
351 2
352
        //convert secs to milliseconds
353
        if (defined('CURLOPT_TIMEOUT_MS')) {
354
            if (!isset($this->options['timeout_ms'])) {
355
                $this->options['timeout_ms'] = intval($this->options['timeout'] * 1000);
356
            } else {
357
                $this->options['timeout_ms'] = intval($this->options['timeout_ms']);
358 2
            }
359
        }
360
361 2
        $cURLOptions = self::filterAndRaw($this->options);
362 2
363 2
        curl_setopt_array($this->curlHandle, $cURLOptions);
364 2
365 2
        return $this;
366
    }
367
368
    public function onEnd(callable $callback)
369
    {
370
        if (!is_callable($callback)) {
371 2
            throw new InvalidArgumentException('callback not is callable :' . print_r($callback, 1));
372 1
        }
373 1
374 2
        $this->endCallback = $callback;
375 2
        return $this;
376 2
    }
377
378 2
    protected static function filterAndRaw(array &$options)
379
    {
380
        $opts = array();
381
        foreach ($options as $key => $val) {
382
            $alias = self::optionAlias($key);
383
            $options[$alias] = $val;
384 2
            if ($alias) {
385
                $opts[constant($alias)] = $val;
386 2
            }
387 2
            unset($options[$key]);
388 2
        }
389 2
        return $opts;
390 2
    }
391
392
    public function makeResponse($isMultiCurl = false)
393
    {
394
        $body = $isMultiCurl ? curl_multi_getcontent($this->curlHandle) : curl_exec($this->curlHandle);
395
        $info = curl_getinfo($this->curlHandle);
396 2
        $errno = curl_errno($this->curlHandle);
397
        $error = curl_error($this->curlHandle);
398 2
        $response = Response::create($this, $body, $info, $errno, $error);
399 2
        if (!is_null(self::$logger)) {
400
            self::log($response);
401
        }
402
403 2
        return $response;
404 1
    }
405
406 1
    private static function log(Response $response)
407
    {
408 2
        if ($response->hasErrors()) {
409 1
            self::$logger->error($response->request->getURI() . "\t" . $response->error, array(
0 ignored issues
show
Bug introduced by
The method getURI() does not seem to exist on object<MultiHttp\Request>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
410
                'response' => print_r($response, 1),
411 1
            ));
412
        }
413 2
414
    }
415
}
416