Passed
Push — master ( b5fad1...c2dd79 )
by Radu
02:19
created

CurlBrowser::debugFinish()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 8
nc 2
nop 0
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php
2
namespace WebServCo\Framework;
3
4
use WebServCo\Framework\Http;
5
use WebServCo\Framework\Exceptions\ApplicationException;
6
7
final class CurlBrowser implements
8
    \WebServCo\Framework\Interfaces\HttpBrowserInterface
9
{
10
    protected $debug = true;
11
    protected $requestHeaders = [];
12
13
    protected $method;
14
    protected $postData;
15
16
    protected $curl;
17
    protected $debugStderr;
18
    protected $debugOutput;
19
    protected $debugInfo;
20
    protected $response;
21
22
    protected $logger;
23
24
    public function __construct($logDir, \WebServCo\Framework\Interfaces\RequestInterface $requestInterface)
25
    {
26
        $this->logger = new \WebServCo\Framework\FileLogger(
27
            'CurlBrowser',
28
            $logDir,
29
            $requestInterface
30
        );
31
        $this->logger->clear();
32
    }
33
34
    public function setDebug(bool $debug)
35
    {
36
        $this->debug = $debug;
37
    }
38
39
    public function setRequestHeaders(array $requestHeaders)
40
    {
41
        $this->requestHeaders = $requestHeaders;
42
    }
43
44
    public function get($url)
45
    {
46
        $this->setMethod(Http::METHOD_GET);
47
        return $this->retrieve($url);
48
    }
49
50
    public function post($url, $postData = [])
51
    {
52
        $this->setMethod(Http::METHOD_POST);
53
        $this->setPostData($postData);
54
        return $this->retrieve($url);
55
    }
56
57
    protected function setMethod($method)
58
    {
59
        if (!in_array($method, Http::getMethods())) {
60
            throw new ApplicationException('Unsupported method');
61
        }
62
        $this->method = $method;
63
        return true;
64
    }
65
66
    protected function setPostData(array $postData)
67
    {
68
        $this->postData = $postData;
69
    }
70
71
    protected function debugInit()
72
    {
73
        if ($this->debug) {
74
            ob_start();
75
            $this->debugStderr = fopen('php://output', 'w');
76
            return true;
77
        }
78
        return false;
79
    }
80
81
    protected function debugDo()
82
    {
83
        if ($this->debug) {
84
            //curl_setopt($this->curl, CURLINFO_HEADER_OUT, 1); /* verbose not working if this is enabled */
85
            curl_setopt($this->curl, CURLOPT_VERBOSE, 1);
86
            curl_setopt($this->curl, CURLOPT_STDERR, $this->debugStderr);
87
            return false;
88
        }
89
        return false;
90
    }
91
92
    protected function debugFinish()
93
    {
94
        if ($this->debug) {
95
            fclose($this->debugStderr);
96
            $this->debugOutput = ob_get_clean();
97
98
            $this->logger->debug('CURL INFO:', $this->debugInfo);
99
            $this->logger->debug('CURL VERBOSE:', $this->debugOutput);
100
            $this->logger->debug('CURL RESPONSE:', $this->response);
101
102
            return true;
103
        }
104
        return false;
105
    }
106
107
    protected function getHttpCode()
108
    {
109
        return isset($this->debugInfo['http_code']) ? $this->debugInfo['http_code']: false;
110
    }
111
112
    protected function parseResponseHeaders($headerString)
113
    {
114
        $headers = [];
115
        $lines = explode("\r\n", $headerString);
116
        foreach ($lines as $index => $line) {
117
            if (0 === $index) {
118
                continue; /* we'll get the status code elsewhere */
119
            }
120
            list($key, $value) = explode(': ', $line);
121
            $headers[$key] = $value;
122
        }
123
        return $headers;
124
    }
125
126
    protected function parseRequestHeaders($headers)
127
    {
128
        $data = [];
129
        foreach ($headers as $k => $v) {
130
            $data[] = sprintf('%s: %s', $k, $v);
131
        }
132
        return $data;
133
    }
134
135
    protected function retrieve($url)
136
    {
137
        $this->debugInit();
138
139
        $this->curl = curl_init();
140
        curl_setopt_array(
141
            $this->curl,
142
            [
143
                CURLOPT_RETURNTRANSFER => true, /* return instead of outputting */
144
                CURLOPT_URL => $url,
145
                CURLOPT_HEADER => true, /* include the header in the output */
146
                CURLOPT_FOLLOWLOCATION => true /* follow redirects */
147
            ]
148
        );
149
        if (!empty($this->requestHeaders)) {
150
            curl_setopt(
151
                $this->curl,
152
                CURLOPT_HTTPHEADER,
153
                $this->parseRequestHeaders($this->requestHeaders)
154
            );
155
        }
156
157
        $this->debugDo();
158
159
        if ($this->method == Http::METHOD_POST) {
160
            curl_setopt($this->curl, CURLOPT_POST, true);
161
            if (!empty($this->postData)) {
162
                curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postData);
163
            }
164
        }
165
166
        $this->response = curl_exec($this->curl);
167
        if (false === $this->response) {
168
            throw new ApplicationException(curl_error($this->curl));
169
        }
170
171
        $this->debugInfo = curl_getinfo($this->curl);
172
173
        $httpCode = $this->getHttpCode();
174
175
        curl_close($this->curl);
176
177
        /**
178
         * For redirects, the response will contain evey header/body pair.
179
         * The last header/body will be at the end of the response.
180
         */
181
        $responseParts = explode("\r\n\r\n", $this->response);
182
        $body = array_pop($responseParts);
183
        $headerString = array_pop($responseParts);
184
185
        $body = trim($body);
186
        $headers = $this->parseResponseHeaders($headerString);
187
188
        $this->debugFinish();
189
190
        return new \WebServCo\Framework\HttpResponse(
191
            $body,
192
            $httpCode,
193
            $headers
194
        );
195
    }
196
}
197