Completed
Push — master ( c7116d...4968a9 )
by Anton
03:06
created

Curl::send()   C

Complexity

Conditions 14
Paths 14

Size

Total Lines 60
Code Lines 41

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 60
rs 6.325
cc 14
eloc 41
nc 14
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
namespace Covery\Client\Transport;
4
5
use Covery\Client\IoException;
6
use Covery\Client\TimeoutException;
7
use Covery\Client\TransportInterface;
8
use GuzzleHttp\Psr7\Response;
9
use Psr\Http\Message\RequestInterface;
10
11
/**
12
 * Class Curl
13
 *
14
 * CURL implementation of Covery Transport
15
 *
16
 * @package Covery\Client\Transport
17
 */
18
class Curl implements TransportInterface
19
{
20
    private $timeoutMillis;
21
22
    /**
23
     * Curl constructor.
24
     *
25
     * @param int|float $timeout Timeout in seconds
26
     * @throws \Exception
27
     */
28
    public function __construct($timeout)
29
    {
30
        if (!is_int($timeout) && !is_float($timeout)) {
31
            throw new \InvalidArgumentException('Timeout must be integer or float');
32
        }
33
        if (!function_exists('curl_init')) {
34
            throw new \Exception('cURL extension not installed/enabled');
35
        }
36
37
        $this->timeoutMillis = floor($timeout * 1000);
38
    }
39
40
    /**
41
     * @inheritDoc
42
     */
43
    public function send(RequestInterface $request)
44
    {
45
        $headers = [];
46
        foreach ($request->getHeaders() as $name => $values) {
47
            $headers[] = $name . ': ' . implode(', ', $values);
48
        }
49
50
        $before = microtime(true);
51
        $curl = curl_init();
52
        curl_setopt($curl, CURLOPT_URL, strval($request->getUri()));
53
        curl_setopt($curl, CURLOPT_CONNECTTIMEOUT_MS, $this->timeoutMillis);
54
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
55
        curl_setopt($curl, CURLOPT_POST, true);
56
        curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getBody()->getContents());
57
        curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
58
        curl_setopt($curl, CURLOPT_HEADER, 1);
59
60
        $response = curl_exec($curl);
61
62
        $status = curl_getinfo($curl, CURLINFO_HTTP_CODE);
63
        $errno  = curl_errno($curl);
64
        $error  = curl_error($curl);
65
        curl_close($curl);
66
67
        if ($errno === CURLE_OPERATION_TIMEOUTED) {
68
            // Timeout
69
            throw new TimeoutException(sprintf('Transport timeout after %.2f seconds wait', microtime(true) - $before));
70
        } elseif ($errno === CURLE_SSL_CACERT
71
            || $errno === CURLE_SSL_CERTPROBLEM
72
            || $errno === CURLE_SSL_CIPHER
73
            || $errno === CURLE_SSL_CONNECT_ERROR
74
            || $errno === CURLE_SSL_PEER_CERTIFICATE
75
            || $errno === CURLE_SSL_ENGINE_NOTFOUND
76
            || $errno === CURLE_SSL_ENGINE_SETFAILED
77
        ) {
78
            // SSL error
79
            throw new IoException('Transport SSL error ' . $error, intval($errno));
80
        } elseif ($errno !== CURLE_OK) {
81
            // Other error
82
            throw new IoException('Curl error ' . $error, intval($errno));
83
        }
84
85
        if ($response === false) {
86
            throw new IoException(sprintf('Curl error. Received status %s, curl error %s', $status, $error));
87
        }
88
89
        list($rawHeaders, $body) = explode("\r\n\r\n", $response, 2);
90
        $rawHeaders = explode("\n", $rawHeaders);
91
        $headers = array();
92
        foreach ($rawHeaders as $row) {
93
            $row = trim($row);
94
            $index = strpos($row, ':');
95
            if ($index > 0) {
96
                $headers[substr($row, 0, $index)] = trim(substr($row, $index + 1));
97
            }
98
        }
99
100
        // Building response
101
        return new Response($status, $headers, $body);
102
    }
103
}
104