Completed
Push — master ( 092247...6dd5e4 )
by Stéphane
06:20 queued 03:28
created

CurlHandle::getCurlInfo()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * This file is part of the bee4/transport package.
4
 * For the full copyright and license information, please view the LICENSE
5
 * file that was distributed with this source code.
6
 *
7
 * @copyright Bee4 2015
8
 * @author  Stephane HULARD <[email protected]>
9
 * @package Bee4\Transport\Handle
10
 */
11
12
namespace Bee4\Transport\Handle;
13
14
use Composer\CaBundle\CaBundle;
15
use Bee4\Transport\Message\Request\AbstractRequest;
16
use Bee4\Transport\Configuration;
17
use Bee4\Transport\Exception\Curl\ExceptionFactory;
18
use Bee4\Transport\Exception\RuntimeException;
19
20
/**
21
 * Define cURL handle wrapper
22
 * @package Bee4\Transport\Handle
23
 */
24
class CurlHandle implements HandleInterface
25
{
26
    /**
27
     * cURL resource handle
28
     * @var resource
29
     */
30
    private $handle;
31
32
    /**
33
     * Option collection used for the current request
34
     * @var array
35
     */
36
    private $options = [];
37
38
    /**
39
     * Initialize cURL resource
40
     */
41 10
    public function __construct()
42
    {
43
        // @codeCoverageIgnoreStart
44
        if (!extension_loaded('curl')) {
45
            throw new RuntimeException('The PHP cURL extension must be installed!');
46
        }
47
        // @codeCoverageIgnoreEnd
48
49 10
        $this->setDefaults();
50 10
        $this->open();
51 10
    }
52
53
    /**
54
     * Set default CURL options
55
     */
56 14
    private function setDefaults()
57
    {
58 14
        $this->options = [
59 14
            CURLOPT_RETURNTRANSFER => true,
60 14
            CURLOPT_FOLLOWLOCATION => true,
61 14
            CURLOPT_HEADER => true,
62 14
            CURLINFO_HEADER_OUT => true
63
        ];
64 14
    }
65
66
    /**
67
     * Handle destructor
68
     * @codeCoverageIgnore
69
     */
70
    public function __destruct()
71
    {
72
        $this->close();
73
    }
74
75
    /**
76
     * Open the curl handle to be used
77
     * @return Handle
78
     */
79 10
    public function open()
80
    {
81 10
        if (!is_resource($this->handle)) {
82 10
            $this->handle = curl_init();
83
        }
84 10
        return $this;
85
    }
86
87
    /**
88
     * Close currently opened handle
89
     * @return Handle
90
     */
91 1
    public function close()
92
    {
93 1
        if (is_resource($this->handle)) {
94 1
            curl_close($this->handle);
95
        }
96 1
        $this->handle = null;
97 1
        return $this;
98
    }
99
100
    /**
101
     * Prepare the handle to be configured by a given request
102
     * @param  AbstractRequest $request
103
     * @return CurlHandle
104
     */
105 11
    public function prepare(AbstractRequest $request)
106
    {
107 11
        $config = $request->getOptions();
108
109 11
        $this->options[CURLOPT_URL] = (string)$config->url;
110 11
        $this->options[CURLOPT_UPLOAD] = (bool)$config->upload;
111 11
        $this->options[CURLOPT_HTTPHEADER] = $request->getHeaderLines();
112
113 11
        if ($config instanceof Configuration\HttpConfiguration) {
114 9
            $this->prepareHttp($config);
115
        }
116 11
        if ($config instanceof Configuration\FtpConfiguration) {
117 1
            $this->options[CURLOPT_FTP_USE_EPSV] = $config->passive;
118 1
            $this->options[CURLOPT_QUOTE] = $config->commandsRequest();
119 1
            $this->options[CURLOPT_POSTQUOTE] = $config->commandsPost();
120
        }
121 11
        if ($config instanceof Configuration\SshConfiguration) {
122
            $this->options[CURLOPT_POSTQUOTE] = $config->commandsPost();
123
        }
124
125 11
        if ($config->hasBody()) {
126 8
            $body = $config->body;
127 8
            if (is_resource($body)) {
128 1
                $this->options[CURLOPT_INFILE] = $body;
129 1
                $md = stream_get_meta_data($body);
130 1
                $this->options[CURLOPT_INFILESIZE] = filesize($md['uri']);
131
            } else {
132 8
                $this->options[CURLOPT_POSTFIELDS] = $body;
133
            }
134
        } else {
135 3
            $this->options[CURLOPT_NOBODY] = true;
136
        }
137
138 11
        return $this;
139
    }
140
141
    /**
142
     * Specific method to prepare HTTP requests options
143
     * @param Configuration\HttpConfiguration $config
144
     */
145 9
    private function prepareHttp(Configuration\HttpConfiguration $config)
146
    {
147 9
        switch ($config->method) {
148 9
            case 'GET':
149 4
                $this->options[CURLOPT_HTTPGET] = true;
150 4
                break;
151 5
            case 'PUT':
152 2
                if (is_resource($config->body)) {
153 1
                    $this->options[CURLOPT_PUT] = true;
154
                } else {
155 1
                    $this->options[CURLOPT_CUSTOMREQUEST] = 'PUT';
156
                }
157 2
                break;
158
            default:
159 3
                $this->options[CURLOPT_CUSTOMREQUEST] = $config->method;
160
        }
161
162 9
        if ($config->redirectsAllowed()) {
163 9
            $this->options[CURLOPT_AUTOREFERER] = $config->allowRedirectsReferer();
164 9
            $this->options[CURLOPT_MAXREDIRS] = $config->allowRedirectsMax();
165
        } else {
166
            $this->options[CURLOPT_FOLLOWLOCATION] = false;
167
        }
168
169 9
        if (null !== $config->accept_encoding) {
170
            $this->options[CURLOPT_ENCODING] = $config->accept_encoding;
171
        }
172
173 9
        if (true === $config->verify) {
174
            $this->options[CURLOPT_SSL_VERIFYPEER] = true;
175
            $this->options[CURLOPT_SSL_VERIFYHOST] = 2;
176
            $this->options[CURLOPT_CAINFO] = CaBundle::getSystemCaRootBundlePath();
177
        } else {
178 9
            $this->options[CURLOPT_SSL_VERIFYPEER] = false;
179 9
            $this->options[CURLOPT_SSL_VERIFYHOST] = 0;
180
        }
181 9
    }
182
183
    /**
184
     * Execute current handle and return result
185
     * @throws RuntimeException
186
     * @throws CurlException
187
     * @return string
188
     */
189 13
    public function execute()
190
    {
191 13
        if (!is_resource($this->handle)) {
192 1
            throw new RuntimeException('Curl handle has been closed, just open it before execute...');
193
        }
194
195 12
        curl_setopt_array($this->handle, array_filter($this->options));
196 12
        $return = curl_exec($this->handle);
197
198 12
        if ($return === false) {
199 2
            throw ExceptionFactory::build(
200 2
                curl_errno($this->handle),
201 2
                curl_error($this->handle)
202
            );
203
        }
204
205 10
        return $return;
206
    }
207
208
    /**
209
     * Check PHP version and reset handle option if possible
210
     * @return boolean
211
     */
212 4
    public function reset()
213
    {
214 4
        if (is_resource($this->handle)) {
215 4
            curl_reset($this->handle);
216 4
            $this->setDefaults();
217 4
            return true;
218
        }
219
220
        return false;
221
    }
222
223
    /**
224
     * Access to `curl_getinfo` result on the current handle
225
     * @return array
226
     */
227
    public function getCurlInfo()
228
    {
229
        return curl_getinfo($this->handle);
230
    }
231
232
    /**
233
     * Retrieve ExecutionInfos details
234
     * @return ExecutionInfos
235
     */
236 11
    public function infos()
237
    {
238 11
        return (new ExecutionInfos($this))
239 11
            ->status(curl_getinfo($this->handle, CURLINFO_HTTP_CODE))
240
            ->headers(curl_getinfo($this->handle, CURLINFO_HEADER_OUT))
241
            ->effectiveUrl(curl_getinfo($this->handle, CURLINFO_EFFECTIVE_URL))
242
            ->transactionTime(curl_getinfo($this->handle, CURLINFO_TOTAL_TIME));
243
    }
244
}
245