Passed
Push — master ( 82e8a0...141c1f )
by Igor
02:31
created

CurlerRequest::setInfile()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3.0052

Importance

Changes 0
Metric Value
dl 0
loc 22
ccs 11
cts 12
cp 0.9167
rs 9.568
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3.0052
1
<?php
2
3
namespace ClickHouseDB\Transport;
4
5
class CurlerRequest
6
{
7
    /**
8
     * @var array
9
     */
10
    public $extendinfo = array();
11
12
    /**
13
     * @var string|array
14
     */
15
    private $parameters = '';
16
17
    /**
18
     * @var array
19
     */
20
    private $options;
21
22
    /**
23
     * @var array
24
     */
25
    private $headers; // Parsed reponse header object.
26
27
    /**
28
     * @var string
29
     */
30
    private $url;
31
32
    /**
33
     * @var string
34
     */
35
    private $method;
36
37
    /**
38
     * @var bool
39
     */
40
    private $id;
41
42
    /**
43
     * @var resource|null
44
     */
45
    private $handle;
46
47
    /**
48
     * @var CurlerResponse
49
     */
50
    private $resp = null;
51
52
    /**
53
     * @var bool
54
     */
55
    private $_persistent = false;
56
57
    /**
58
     * @var bool
59
     */
60
    private $_attachFiles = false;
61
62
    /**
63
     * @var string
64
     */
65
    private $callback_class = '';
66
67
    /**
68
     * @var string
69
     */
70
    private $callback_functionName = '';
71
72
    /**
73
     * @var bool
74
     */
75
    private $_httpCompression = false;
76
77
    /**
78
     * @var callable
79
     */
80
    private $callback_function = null;
81
82
    /**
83
     * @var bool|resource
84
     */
85
    private $infile_handle = false;
86
87
    /**
88
     * @var int
89
     */
90
    private $_dns_cache = 120;
91
92
    /**
93
     * @var resource
94
     */
95
    private $resultFileHandle = null;
96
97
    /**
98
     * @param bool $id
99
     */
100 36
    public function __construct($id = false)
101
    {
102 36
        $this->id = $id;
103
104 36
        $this->header('Cache-Control', 'no-cache, no-store, must-revalidate');
105 36
        $this->header('Expires', '0');
106 36
        $this->header('Pragma', 'no-cache');
107
108 36
        $this->options = array(
109 36
            CURLOPT_SSL_VERIFYHOST => 0,
110 36
            CURLOPT_SSL_VERIFYPEER => false,
111 36
            CURLOPT_TIMEOUT => 10,
112 36
            CURLOPT_CONNECTTIMEOUT => 5, // Количество секунд ожидания при попытке соединения
113 36
            CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
114 36
            CURLOPT_MAXREDIRS => 10,
115 36
            CURLOPT_HEADER => TRUE,
116 36
            CURLOPT_FOLLOWLOCATION => TRUE,
117 36
            CURLOPT_AUTOREFERER => 1, // при редиректе подставлять в «Referer:» значение из «Location:»
118 36
            CURLOPT_BINARYTRANSFER => 1, // передавать в binary-safe
119 36
            CURLOPT_RETURNTRANSFER => TRUE,
120 36
            CURLOPT_USERAGENT => 'smi2/PHPClickHouse/client',
121
        );
122 36
    }
123
124
    /**
125
     *
126
     */
127 35
    public function __destruct()
128
    {
129 35
        $this->close();
130 35
    }
131
132
133 35
    public function close()
134
    {
135 35
        if ($this->handle)
136
        {
137 35
            curl_close($this->handle);
138
        }
139 35
        $this->handle = null;
140 35
    }
141
142
    /**
143
     * @param array $attachFiles
144
     */
145 1
    public function attachFiles($attachFiles)
146
    {
147 1
        $this->header("Content-Type", "multipart/form-data");
148
149 1
        $out = [];
150 1
        foreach ($attachFiles as $post_name => $file_path) {
151 1
            $out[$post_name] = new \CURLFile($file_path);
152
        }
153
154 1
        $this->_attachFiles = true;
155 1
        $this->parameters($out);
156 1
    }
157
158
159
    /**
160
     * @param bool $set
161
     * @return $this
162
     */
163
    public function id($set = false)
164
    {
165
        if ($set) {
166
            $this->id = $set;
167
        }
168
169
        return $this;
170
    }
171
172
    /**
173
     * @param array $params
174
     * @return $this
175
     */
176 36
    public function setRequestExtendedInfo($params)
177
    {
178 36
        $this->extendinfo = $params;
179 36
        return $this;
180
    }
181
182
    /**
183
     * @param string|integer|null $key
184
     * @return mixed
185
     */
186 36
    public function getRequestExtendedInfo($key = null)
187
    {
188 36
        if ($key) {
189 36
            return isset($this->extendinfo[$key]) ? $this->extendinfo[$key] : false;
190
        }
191
192
        return $this->extendinfo;
193
    }
194
195
    /**
196
     * @return bool|resource
197
     */
198 7
    public function getInfileHandle()
199
    {
200 7
        return $this->infile_handle;
201
    }
202
203
    /**
204
     * @param string $file_name
205
     * @return bool|resource
206
     */
207 7
    public function setInfile($file_name)
208
    {
209 7
        $this->header('Expect', '');
210 7
        $this->infile_handle = fopen($file_name, 'r');
211 7
        if (is_resource($this->infile_handle))
212
        {
213
214 7
            if ($this->_httpCompression) {
215 7
                $this->header('Content-Encoding', 'gzip');
216 7
                $this->header('Content-Type', 'application/x-www-form-urlencoded');
217
218 7
                stream_filter_append($this->infile_handle, 'zlib.deflate', STREAM_FILTER_READ, ["window" => 30]);
219
220 7
                $this->options[CURLOPT_SAFE_UPLOAD] = 1;
221
            } else {
222
                $this->options[CURLOPT_INFILESIZE] = filesize($file_name);
223
            }
224
225 7
            $this->options[CURLOPT_INFILE] = $this->infile_handle;
226
        }
227
228 7
        return $this->infile_handle;
229
    }
230
231
    /**
232
     * @param callable $callback
233
     */
234 7
    public function setCallbackFunction($callback)
235
    {
236 7
        $this->callback_function = $callback;
237 7
    }
238
239
    /**
240
     * @param callable $callback
241
     */
242 2
    public function setReadFunction($callback)
243
    {
244 2
        $this->options[CURLOPT_READFUNCTION] = $callback;
245 2
    }
246
247
    /**
248
     * @param string $classCallBack
249
     * @param string $functionName
250
     */
251
    public function setCallback($classCallBack, $functionName)
252
    {
253
        $this->callback_class = $classCallBack;
254
        $this->callback_functionName = $functionName;
255
    }
256
257
    /**
258
     *
259
     */
260 8
    public function onCallback()
261
    {
262 8
        if ($this->callback_function) {
263 7
            $x = $this->callback_function;
264 7
            $x($this);
265
        }
266
267 8
        if ($this->callback_class && $this->callback_functionName) {
268
            $c = $this->callback_functionName;
269
            $this->callback_class->$c($this);
270
        }
271 8
    }
272
273
    /**
274
     * @param bool $result
275
     * @return string
276
     */
277
    public function dump($result = false)
278
    {
279
        $message = "\n------------  Request ------------\n";
280
        $message .= 'URL:' . $this->url . "\n\n";
281
        $message .= 'METHOD:' . $this->method . "\n\n";
282
        $message .= 'PARAMS:' . print_r($this->parameters, true) . "\n";
283
        $message .= 'PARAMS:' . print_r($this->headers, true) . "\n";
284
        $message .= "-----------------------------------\n";
285
286
        if ($result) {
287
            return $message;
288
        }
289
290
        echo $message;
291
        return '';
292
    }
293
294
    /**
295
     * @return bool
296
     */
297 11
    public function getId()
298
    {
299 11
        return $this->id;
300
    }
301
302
    /**
303
     * @param integer $key
304
     * @param mixed $value
305
     * @return $this
306
     */
307 1
    private function option($key, $value)
308
    {
309 1
        $this->options[$key] = $value;
310 1
        return $this;
311
    }
312
313
    /**
314
     * @return $this
315
     */
316 1
    public function persistent()
317
    {
318 1
        $this->_persistent = true;
319 1
        return $this;
320
    }
321
322
    /**
323
     * @return bool
324
     */
325 8
    public function isPersistent()
326
    {
327 8
        return $this->_persistent;
328
    }
329
330
    /**
331
     * @param int $sec
332
     * @return $this
333
     */
334 36
    public function keepAlive($sec = 60)
335
    {
336 36
        $this->options[CURLOPT_FORBID_REUSE] = TRUE;
337 36
        $this->headers['Connection'] = 'Keep-Alive';
338 36
        $this->headers['Keep-Alive'] = $sec;
339
340 36
        return $this;
341
    }
342
343
    /**
344
     * @param bool $flag
345
     * @return $this
346
     */
347 36
    public function verbose($flag = true)
348
    {
349 36
        $this->options[CURLOPT_VERBOSE] = $flag;
350 36
        return $this;
351
    }
352
353
    /**
354
     * @param string $key
355
     * @param string $value
356
     * @return $this
357
     */
358 36
    public function header($key, $value)
359
    {
360 36
        $this->headers[$key] = $value;
361 36
        return $this;
362
    }
363
364
    /**
365
     * @return array
366
     */
367
    public function getHeaders()
368
    {
369
        $head = [];
370
        foreach ($this->headers as $key=>$value) {
371
                    $head[] = sprintf("%s: %s", $key, $value);
372
        }
373
        return $head;
374
    }
375
376
    /**
377
     * @param string $url
378
     * @return $this
379
     */
380 36
    public function url($url)
381
    {
382 36
        $this->url = $url;
383 36
        return $this;
384
    }
385
386
    /**
387
     * @return mixed
388
     */
389
    public function getUrl()
390
    {
391
        return $this->url;
392
    }
393
394
395
    /**
396
     * @param string $id
397
     * @return string
398
     */
399 11
    public function getUniqHash($id)
400
    {
401 11
        return $id . '.' . microtime() . mt_rand(0, 1000000);
402
    }
403
404
    /**
405
     * @param bool $flag
406
     */
407 27
    public function httpCompression($flag)
408
    {
409 27
        if ($flag) {
410 27
            $this->_httpCompression = $flag;
411 27
            $this->options[CURLOPT_ENCODING] = 'gzip';
412
        } else
413
        {
414
            $this->_httpCompression = false;
415
            unset($this->options[CURLOPT_ENCODING]);
416
        }
417 27
    }
418
419
    /**
420
     * @param string $username
421
     * @param string $password
422
     * @return $this
423
     */
424 36
    public function auth($username, $password)
425
    {
426 36
        $this->options[CURLOPT_USERPWD] = sprintf("%s:%s", $username, $password);
427 36
        return $this;
428
    }
429
430
    /**
431
     * @param array|string $data
432
     * @return $this
433
     */
434 1
    public function parameters($data)
435
    {
436 1
        $this->parameters = $data;
437 1
        return $this;
438
    }
439
440
    /**
441
     * The number of seconds to wait when trying to connect. Use 0 for infinite waiting.
442
     *
443
     * @param int $seconds
444
     * @return $this
445
     */
446 36
    public function connectTimeOut($seconds = 1)
447
    {
448 36
        $this->options[CURLOPT_CONNECTTIMEOUT] = $seconds;
449 36
        return $this;
450
    }
451
452
    /**
453
     * The maximum number of seconds (float) allowed to execute cURL functions.
454
     *
455
     * @param float $seconds
456
     * @return $this
457
     */
458 36
    public function timeOut($seconds = 10)
459
    {
460 36
        return $this->timeOutMs(intval($seconds * 1000));
461
    }
462
463
    /**
464
     * The maximum allowed number of milliseconds to perform cURL functions.
465
     *
466
     * @param int $ms millisecond
467
     * @return $this
468
     */
469 36
    protected function timeOutMs($ms = 10000)
470
    {
471 36
        $this->options[CURLOPT_TIMEOUT_MS] = $ms;
472 36
        return $this;
473
    }
474
475
476
    /**
477
     * @param array|mixed $data
478
     * @return $this
479
     * @throws \ClickHouseDB\Exception\TransportException
480
     */
481 36
    public function parameters_json($data)
482
    {
483
484 36
        $this->header("Content-Type", "application/json, text/javascript; charset=utf-8");
485 36
        $this->header("Accept", "application/json, text/javascript, */*; q=0.01");
486
487 36
        if ($data === null) {
488
            $this->parameters = '{}';
489
            return $this;
490
        }
491
492 36
        if (is_string($data)) {
493 36
            $this->parameters = $data;
494 36
            return $this;
495
        }
496
497
        $this->parameters = json_encode($data);
498
499
        if (!$this->parameters && $data) {
500
            throw new \ClickHouseDB\Exception\TransportException('Cant json_encode: ' . strval($data));
501
        }
502
503
        return $this;
504
    }
505
506
    /**
507
     * @return resource
508
     */
509
    public function getResultFileHandle()
510
    {
511
        return $this->resultFileHandle;
512
    }
513
514
    /**
515
     * @return bool
516
     */
517
    public function isResultFile()
518
    {
519
        return ($this->resultFileHandle ? true : false);
520
    }
521
522
    /**
523
     * @param resource $h resource
524
     * @param bool $zlib
525
     * @return $this
526
     */
527 1
    public function setResultFileHandle($h, $zlib = false)
528
    {
529 1
        $this->resultFileHandle = $h;
530 1
        if ($zlib) {
531
            $params = array('level' => 6, 'window' => 15, 'memory' => 9);
532
            stream_filter_append($this->resultFileHandle, 'zlib.deflate', STREAM_FILTER_WRITE, $params);
533
        }
534 1
        return $this;
535
    }
536
537
    /**
538
     * @return CurlerRequest
539
     */
540
    public function PUT()
541
    {
542
        return $this->execute('PUT');
543
    }
544
545
    /**
546
     * @return CurlerRequest
547
     */
548 36
    public function POST()
549
    {
550 36
        return $this->execute('POST');
551
    }
552
553
    /**
554
     * @return CurlerRequest
555
     */
556
    public function OPTIONS()
557
    {
558
        return $this->execute('OPTIONS');
559
    }
560
561
    /**
562
     * @return CurlerRequest
563
     */
564
    public function GET()
565
    {
566
        return $this->execute('GET');
567
    }
568
569
    /**
570
     * The number of seconds that DNS records are stored in memory. By default this parameter is 120 (2 minutes).
571
     *
572
     * @param integer $set
573
     * @return $this
574
     */
575
    public function setDnsCache($set)
576
    {
577
        $this->_dns_cache = $set;
578
        return $this;
579
    }
580
581
    /**
582
     * The number of seconds that DNS records are stored in memory. By default this parameter is 120 (2 minutes).
583
     *
584
     * @return int
585
     */
586 35
    public function getDnsCache()
587
    {
588 35
        return $this->_dns_cache;
589
    }
590
591
    /**
592
     * @param string $method
593
     * @return $this
594
     */
595 36
    private function execute($method)
596
    {
597 36
        $this->method = $method;
598 36
        return $this;
599
    }
600
601
    /**
602
     * @return CurlerResponse
603
     * @throws \ClickHouseDB\Exception\TransportException
604
     */
605 35
    public function response()
606
    {
607 35
        if (!$this->resp) {
608
            throw new \ClickHouseDB\Exception\TransportException('Can`t fetch response - is empty');
609
        }
610
611 35
        return $this->resp;
612
    }
613
614
    /**
615
     * @return bool
616
     */
617 35
    public function isResponseExists()
618
    {
619 35
        return ($this->resp ? true : false);
620
    }
621
622 35
    public function setResponse(CurlerResponse $response)
623
    {
624 35
        $this->resp = $response;
625 35
    }
626
627
    /**
628
     * @return mixed
629
     */
630 35
    public function handle()
631
    {
632 35
        $this->prepareRequest();
633 35
        return $this->handle;
634
    }
635
636
    /**
637
     * @param callable $callback
638
     * @throws \Exception
639
     */
640 1
    public function setFunctionProgress(callable $callback)
641
    {
642 1
        if (!is_callable($callback)) {
643
            throw new \Exception('setFunctionProgress not is_callable');
644
        }
645
646 1
        $this->option(CURLOPT_NOPROGRESS, false);
647 1
        $this->option(CURLOPT_PROGRESSFUNCTION, $callback); // version 5.5.0
648 1
    }
649
650
651
    /**
652
     * @return bool
653
     */
654 35
    private function prepareRequest()
655
    {
656 35
        if (!$this->handle) {
657 35
            $this->handle = curl_init();
658
        }
659
660 35
        $curl_opt = $this->options;
661 35
        $method = $this->method;
662
663 35
        if ($this->_attachFiles) {
664 1
            $curl_opt[CURLOPT_SAFE_UPLOAD] = true;
665
        }
666
667
668 35
        if (strtoupper($method) == 'GET') {
669
            $curl_opt[CURLOPT_HTTPGET] = TRUE;
670
            $curl_opt[CURLOPT_CUSTOMREQUEST] = strtoupper($method);
671
            $curl_opt[CURLOPT_POSTFIELDS] = false;
672
        } else {
673 35
            if (strtoupper($method) === 'POST') {
674 35
                $curl_opt[CURLOPT_POST] = TRUE;
675
            }
676
677 35
            $curl_opt[CURLOPT_CUSTOMREQUEST] = strtoupper($method);
678
679 35
            if ($this->parameters) {
680 35
                $curl_opt[CURLOPT_POSTFIELDS] = $this->parameters;
681
682 35
                if (!is_array($this->parameters)) {
683 35
                    $this->header('Content-Length', strlen($this->parameters));
684
                }
685
            }
686
        }
687
        // CURLOPT_DNS_CACHE_TIMEOUT - Количество секунд, в течение которых в памяти хранятся DNS-записи.
688 35
        $curl_opt[CURLOPT_DNS_CACHE_TIMEOUT] = $this->getDnsCache();
689 35
        $curl_opt[CURLOPT_URL] = $this->url;
690
691 35
        if (!empty($this->headers) && sizeof($this->headers)) {
692 35
            $curl_opt[CURLOPT_HTTPHEADER] = array();
693
694 35
            foreach ($this->headers as $key => $value) {
695 35
                $curl_opt[CURLOPT_HTTPHEADER][] = sprintf("%s: %s", $key, $value);
696
            }
697
        }
698
699 35
        if (!empty($curl_opt[CURLOPT_INFILE])) {
700
701 7
            $curl_opt[CURLOPT_PUT] = true;
702
        }
703
704 35
        if ($this->resultFileHandle) {
705 1
            $curl_opt[CURLOPT_FILE] = $this->resultFileHandle;
706 1
            $curl_opt[CURLOPT_HEADER] = false;
707
        }
708
709 35
        if ($this->options[CURLOPT_VERBOSE]) {
710
            echo "\n-----------BODY REQUEST----------\n" . $curl_opt[CURLOPT_POSTFIELDS] . "\n------END--------\n";
711
        }
712 35
        curl_setopt_array($this->handle, $curl_opt);
713 35
        return true;
714
    }
715
}
716