Completed
Push — master ( a3ffde...c5a0e4 )
by Dev
03:12
created

Request::setDownloadOnly()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 5
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
namespace PiedWeb\Curl;
4
5
class Request
6
{
7
    use UserAgentTrait, StaticWrapperTrait;
8
9
    const  RETURN_HEADER_ONLY = 2;
10
    const  RETURN_HEADER = 1;
11
12
    /**
13
     * Curl resource handle.
14
     *
15
     * @var resource
16
     */
17
    private $handle;
18
19
    /** @var string contains targeted URL */
20
    private $url;
21
22
    /** @var string contains current UA */
23
    private $userAgent;
24
25
    /** @var int */
26
    private $returnHeaders = 0;
27
28
    /** @var mixed */
29
    private $filter;
30
31
    /** @var bool */
32
    private $optChangeDuringRequest = false;
33
34
    /**
35
     * Constructor.
36
     *
37
     * @param string $ur to request
38
     */
39 33
    public function __construct(?string $url = null)
40
    {
41 33
        $this->handle = curl_init();
42 33
        $this->setOpt(CURLOPT_RETURNTRANSFER, 1);
43
44 33
        if (null !== $url) {
45 33
            $this->setUrl($url);
46
        }
47 33
    }
48
49 33
    public function getHandle()
50
    {
51 33
        return $this->handle;
52
    }
53
54 6
    public function getUrl()
55
    {
56 6
        return $this->url;
57
    }
58
59
    /**
60
     * Change the URL to cURL.
61
     *
62
     * @param string $url to request
63
     *
64
     * @return self
65
     */
66 33
    public function setUrl(string $url)
67
    {
68 33
        $this->url = $url;
69 33
        $this->setOpt(CURLOPT_URL, $url);
70
71 33
        return $this;
72
    }
73
74
    /**
75
     * Add a cURL's option.
76
     *
77
     * @param int   $option cURL Predefined Constant
78
     * @param mixed $value
79
     *
80
     * @return self
81
     */
82 33
    public function setOpt($option, $value)
83
    {
84 33
        curl_setopt($this->handle, $option, $value);
85
86 33
        return $this;
87
    }
88
89
    /**
90
     * A short way to set some classic options to cURL a web page.
91
     *
92
     * @return self
93
     */
94 24
    public function setDefaultGetOptions(
95
        $connectTimeOut = 5,
96
        $timeOut = 10,
97
        $dnsCacheTimeOut = 600,
98
        $followLocation = true,
99
        $maxRedirs = 5
100
    ) {
101
        $this
102 24
            ->setOpt(CURLOPT_AUTOREFERER, 1)
103 24
            ->setOpt(CURLOPT_FOLLOWLOCATION, $followLocation)
104 24
            ->setOpt(CURLOPT_MAXREDIRS, $maxRedirs)
105 24
            ->setOpt(CURLOPT_CONNECTTIMEOUT, $connectTimeOut)
106 24
            ->setOpt(CURLOPT_DNS_CACHE_TIMEOUT, $dnsCacheTimeOut)
107 24
            ->setOpt(CURLOPT_TIMEOUT, $timeOut)
108
             //->setOpt(CURLOPT_SSL_VERIFYPEER,    0);
109
        ;
110
111 24
        return $this;
112
    }
113
114
    /**
115
     * A short way to set some classic options to cURL a web page quickly
116
     * (but loosing some data like header, cookie...).
117
     *
118
     * @return self
119
     */
120 9
    public function setDefaultSpeedOptions()
121
    {
122 9
        $this->setOpt(CURLOPT_SSL_VERIFYHOST, 0);
123 9
        $this->setOpt(CURLOPT_SSL_VERIFYPEER, 0);
124
125 9
        if (!$this->returnHeaders) {
126 9
            $this->setOpt(CURLOPT_HEADER, 0);
127
        }
128
129 9
        $this->setDefaultGetOptions(5, 10, 600, true, 1);
130 9
        $this->setEncodingGzip();
131
132 9
        return $this;
133
    }
134
135
    /**
136
     * A short way to not follow redirection.
137
     *
138
     * @return self
139
     */
140 6
    public function setNoFollowRedirection()
141
    {
142
        return $this
143 6
            ->setOpt(CURLOPT_FOLLOWLOCATION, false)
144 6
            ->setOpt(CURLOPT_MAXREDIRS, 0)
145
        ;
146
    }
147
148
    /**
149
     * Call it if you want header informations.
150
     * After self::exec(), you would have this informations with getHeader();.
151
     *
152
     * @return self
153
     */
154 21
    public function setReturnHeader($only = false)
155
    {
156 21
        $this->setOpt(CURLOPT_HEADER, 1);
157 21
        $this->returnHeaders = $only ? self::RETURN_HEADER_ONLY : self::RETURN_HEADER;
158
159 21
        if ($only) {
160 3
            $this->setOpt(CURLOPT_RETURNTRANSFER, 0);
161 3
            $this->setOpt(CURLOPT_NOBODY, 1);
162
        }
163
164 21
        return $this;
165
    }
166
167 24
    public function mustReturnHeaders()
168
    {
169 24
        return $this->returnHeaders;
170
    }
171
172
    /**
173
     * An self::setOpt()'s alias to add a cookie to your request.
174
     *
175
     * @param string $cookie
176
     *
177
     * @return self
178
     */
179 3
    public function setCookie($cookie)
180
    {
181 3
        $this->setOpt(CURLOPT_COOKIE, $cookie);
182
183 3
        return $this;
184
    }
185
186
    /**
187
     * An self::setOpt()'s alias to add a referer to your request.
188
     *
189
     * @param string $referer
190
     *
191
     * @return self
192
     */
193 24
    public function setReferer($referer)
194
    {
195 24
        $this->setOpt(CURLOPT_REFERER, $referer);
196
197 24
        return $this;
198
    }
199
200
    /**
201
     * An self::setOpt()'s alias to add an user-agent to your request.
202
     *
203
     * @param string $ua
204
     *
205
     * @return self
206
     */
207 24
    public function setUserAgent(string $ua)
208
    {
209 24
        $this->userAgent = $ua;
210
211 24
        $this->setOpt(CURLOPT_USERAGENT, $ua);
212
213 24
        return $this;
214
    }
215
216 3
    public function getUserAgent()
217
    {
218 3
        return $this->userAgent;
219
    }
220
221
    /**
222
     * A short way to set post's options to cURL a web page.
223
     *
224
     * @param mixed $post if it's an array, will be converted via http build query
225
     *
226
     * @return self
227
     */
228 3
    public function setPost($post)
229
    {
230 3
        $this->setOpt(CURLOPT_CUSTOMREQUEST, 'POST');
231 3
        $this->setOpt(CURLOPT_POST, 1);
232 3
        $this->setOpt(CURLOPT_POSTFIELDS, is_array($post) ? http_build_query($post) : $post);
233
234 3
        return $this;
235
    }
236
237
    /**
238
     * If you want to request the URL and hope get the result gzipped.
239
     * The output will be automatically uncompress with exec();.
240
     *
241
     * @return self
242
     */
243 24
    public function setEncodingGzip()
244
    {
245 24
        $this->setOpt(CURLOPT_ENCODING, 'gzip, deflate');
246
247 24
        return $this;
248
    }
249
250
    /**
251
     * If you want to request the URL with a (http|socks...) proxy (public or private).
252
     *
253
     * @param string $proxy [scheme]IP:PORT[:LOGIN:PASSWORD]
254
     *                      Eg. : socks5://98.023.023.02:1098:cUrlRequestProxId:SecretPassword
255
     *
256
     * @return self
257
     */
258 3
    public function setProxy(string $proxy)
259
    {
260 3
        $scheme = Helper::getSchemeFrom($proxy);
261 3
        $proxy = explode(':', $proxy);
262 3
        $this->setOpt(CURLOPT_HTTPPROXYTUNNEL, 1);
263 3
        $this->setOpt(CURLOPT_PROXY, $scheme.$proxy[0].':'.$proxy[1]);
264 3
        if (isset($proxy[2])) {
265
            $this->setOpt(CURLOPT_PROXYUSERPWD, $proxy[2].':'.$proxy[3]);
266
        }
267
268 3
        return $this;
269
    }
270
271
    /**
272
     * @param mixed $func function wich must return boolean
273
     *
274
     * @return self
275
     */
276 18
    public function setDownloadOnlyIf(callable $func)
277
    {
278 18
        $this->setReturnHeader();
279
280 18
        $this->filter = $func;
281 18
        $this->setOpt(CURLOPT_HEADERFUNCTION, [$this, 'checkHeader']);
282 18
        $this->setOpt(CURLOPT_NOBODY, 1);
283
284 18
        return $this;
285
    }
286
287
    /**
288
     * @param int $tooBig Default 2000000 = 2000 Kbytes = 2 Mo
289
     *
290
     * @return self
291
     */
292 3
    public function setAbortIfTooBig(int $tooBig = 2000000)
293
    {
294
        //$this->setOpt(CURLOPT_BUFFERSIZE, 128); // more progress info
295 3
        $this->setOpt(CURLOPT_NOPROGRESS, false);
296 1
        $this->setOpt(CURLOPT_PROGRESSFUNCTION, function ($ch, $totalBytes, $receivedBytes) use ($tooBig) {
297 3
            if ($receivedBytes > $tooBig) {
298 3
                return 1;
299
            }
300 3
        });
301
302 3
        return $this;
303
    }
304
305 3
    public function setDownloadOnly($range = '0-500')
306
    {
307 3
        $this->setOpt(CURLOPT_RANGE, $range);
308
309 3
        return $this;
310
    }
311
312 18
    public function checkHeader($handle, $line)
313
    {
314 18
        if (is_string($line)) {
315 18
            if (call_user_func($this->filter, $line)) {
316 12
                $this->optChangeDuringRequest = true;
317 12
                $this->setOpt(CURLOPT_NOBODY, 0);
318
            }
319
        }
320
321 18
        return strlen($line);
322
    }
323
324
    /**
325
     * Execute the request.
326
     *
327
     * @return Response|int corresponding to the curl error
328
     */
329 33
    public function exec($optChange = false)
330
    {
331 33
        $return = Response::get($this);
332
333
        // Permits to transform HEAD request in GET request
334 33
        if ($this->optChangeDuringRequest && false === $optChange) {
335 12
            $this->optChangeDuringRequest = true;
336
337 12
            return $this->exec(true);
338
        }
339
340 33
        if ($return instanceof Response) {
341 24
            $this->setReferer($return->getEffectiveUrl());
342
        }
343
344 33
        return $return;
345
    }
346
347
    /**
348
     * Return the last error number (curl_errno).
349
     *
350
     * @return int the error number or 0 (zero) if no error occurred
351
     */
352 3
    public function hasError()
353
    {
354 3
        return curl_errno($this->handle);
355
    }
356
357
    /**
358
     * Return a string containing the last error for the current session (curl_error).
359
     *
360
     * @return string the error message or '' (the empty string) if no error occurred
361
     */
362 3
    public function getError()
363
    {
364 3
        return curl_error($this->handle);
365
    }
366
367
    /**
368
     * Get information regarding the request.
369
     *
370
     * @param int $opt This may be one of the following constants:
371
     *                 http://php.net/manual/en/function.curl-getinfo.php
372
     *
373
     * @return array|string|false
374
     */
375 3
    public function getInfo(?int $opt)
376
    {
377 3
        return $opt ? curl_getinfo($this->handle, $opt) : curl_getinfo($this->handle);
378
    }
379
380
    /**
381
     * Close the connexion
382
     * Call curl_reset function.
383
     */
384 3
    public function close()
385
    {
386 3
        curl_reset($this->handle);
387 3
    }
388
}
389