Passed
Push — master ( e53bbb...b4aef6 )
by Radu
01: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 setRequestHeaders(array $requestHeaders)
35
    {
36
        $this->requestHeaders = $requestHeaders;
37
    }
38
39
    public function get($url)
40
    {
41
        $this->setMethod(Http::METHOD_GET);
42
        return $this->retrieve($url);
43
    }
44
45
    public function post($url, $postData = [])
46
    {
47
        $this->setMethod(Http::METHOD_POST);
48
        $this->setPostData($postData);
49
        return $this->retrieve($url);
50
    }
51
52
    protected function setMethod($method)
53
    {
54
        if (!in_array($method, Http::getMethods())) {
55
            throw new ApplicationException('Unsupported method');
56
        }
57
        $this->method = $method;
58
        return true;
59
    }
60
61
    protected function setPostData(array $postData)
62
    {
63
        $this->postData = $postData;
64
    }
65
66
    protected function debugInit()
67
    {
68
        if ($this->debug) {
69
            ob_start();
70
            $this->debugStderr = fopen('php://output', 'w');
71
            return true;
72
        }
73
        return false;
74
    }
75
76
    protected function debugDo()
77
    {
78
        if ($this->debug) {
79
            //curl_setopt($this->curl, CURLINFO_HEADER_OUT, 1); /* verbose not working if this is enabled */
80
            curl_setopt($this->curl, CURLOPT_VERBOSE, 1);
81
            curl_setopt($this->curl, CURLOPT_STDERR, $this->debugStderr);
82
            return false;
83
        }
84
        return false;
85
    }
86
87
    protected function debugFinish()
88
    {
89
        if ($this->debug) {
90
            fclose($this->debugStderr);
91
            $this->debugOutput = ob_get_clean();
92
93
            $this->logger->debug('CURL INFO:', $this->debugInfo);
94
            $this->logger->debug('CURL VERBOSE:', $this->debugOutput);
95
            $this->logger->debug('CURL RESPONSE:', $this->response);
96
97
            return true;
98
        }
99
        return false;
100
    }
101
102
    protected function getHttpCode()
103
    {
104
        return isset($this->debugInfo['http_code']) ? $this->debugInfo['http_code']: false;
105
    }
106
107
    protected function parseResponseHeaders($headerString)
108
    {
109
        $headers = [];
110
        $lines = explode("\r\n", $headerString);
111
        foreach ($lines as $index => $line) {
112
            if (0 === $index) {
113
                continue; /* we'll get the status code elsewhere */
114
            }
115
            list($key, $value) = explode(': ', $line);
116
            $headers[$key] = $value;
117
        }
118
        return $headers;
119
    }
120
121
    protected function parseRequestHeaders($headers)
122
    {
123
        $data = [];
124
        foreach ($headers as $k => $v) {
125
            $data[] = sprintf('%s: %s', $k, $v);
126
        }
127
        return $data;
128
    }
129
130
    protected function retrieve($url)
131
    {
132
        $this->debugInit();
133
134
        $this->curl = curl_init();
135
        curl_setopt_array(
136
            $this->curl,
137
            [
138
                CURLOPT_RETURNTRANSFER => true, /* return instead of outputting */
139
                CURLOPT_URL => $url,
140
                CURLOPT_HEADER => true, /* include the header in the output */
141
                CURLOPT_FOLLOWLOCATION => true /* follow redirects */
142
            ]
143
        );
144
        if (!empty($this->requestHeaders)) {
145
            curl_setopt(
146
                $this->curl,
147
                CURLOPT_HTTPHEADER,
148
                $this->parseRequestHeaders($this->requestHeaders)
149
            );
150
        }
151
152
        $this->debugDo();
153
154
        if ($this->method == Http::METHOD_POST) {
155
            curl_setopt($this->curl, CURLOPT_POST, true);
156
            if (!empty($this->postData)) {
157
                curl_setopt($this->curl, CURLOPT_POSTFIELDS, $this->postData);
158
            }
159
        }
160
161
        $this->response = curl_exec($this->curl);
162
        if (false === $this->response) {
163
            throw new ApplicationException(curl_error($this->curl));
164
        }
165
166
        $this->debugInfo = curl_getinfo($this->curl);
167
168
        $httpCode = $this->getHttpCode();
169
170
        curl_close($this->curl);
171
172
        /**
173
         * For redirects, the response will contain evey header/body pair.
174
         * The last header/body will be at the end of the response.
175
         */
176
        $responseParts = explode("\r\n\r\n", $this->response);
177
        $body = array_pop($responseParts);
178
        $headerString = array_pop($responseParts);
179
180
        $body = trim($body);
181
        $headers = $this->parseResponseHeaders($headerString);
182
183
        $this->debugFinish();
184
185
        return new \WebServCo\Framework\HttpResponse(
186
            $body,
187
            $httpCode,
188
            $headers
189
        );
190
    }
191
}
192