Completed
Branch master (23259a)
by Sergey
04:17 queued 48s
created

CurlHttpClient   A

Complexity

Total Complexity 29

Size/Duplication

Total Lines 334
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 334
rs 10
c 0
b 0
f 0
wmc 29

21 Methods

Rating   Name   Duplication   Size   Complexity  
A loadCookies() 0 5 1
A execute() 0 5 1
A callCurl() 0 11 1
A __construct() 0 3 1
A cookie() 0 3 1
A setCookiesPath() 0 5 1
A initCookieFile() 0 10 2
A getDefaultHttpOptions() 0 12 1
A init() 0 13 2
A removeCookies() 0 9 2
A getCookiesPath() 0 3 2
A fillCookies() 0 7 2
A useSocksProxy() 0 3 1
A cookies() 0 3 1
A useProxy() 0 13 3
A initCookieJar() 0 5 1
A getCurrentUrl() 0 3 1
A dontUseProxy() 0 10 1
A usesProxy() 0 3 1
A setOptions() 0 5 1
A makeHttpOptions() 0 14 2
1
<?php
2
3
namespace seregazhuk\PinterestBot\Api;
4
5
use seregazhuk\PinterestBot\Helpers\Cookies;
6
use seregazhuk\PinterestBot\Helpers\UrlBuilder;
7
use seregazhuk\PinterestBot\Api\Contracts\HttpClient;
8
9
/**
10
 * Class CurlHttpClient.
11
 */
12
class CurlHttpClient implements HttpClient
13
{
14
    /**
15
     * Custom CURL options for requests.
16
     *
17
     * @var array
18
     */
19
    protected $options = [
20
        CURLOPT_USERAGENT => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'
21
    ];
22
23
    /**
24
     * @var array
25
     */
26
    protected $headers = [];
27
28
    /**
29
     * Contains the curl instance.
30
     *
31
     * @var resource
32
     */
33
    protected $curl;
34
35
    /**
36
     * Path to cookies file
37
     * @var string
38
     */
39
    protected $cookieJar;
40
41
    /**
42
     * Cookies container
43
     *
44
     * @var Cookies
45
     */
46
    protected $cookies;
47
48
    /**
49
     * @var string
50
     */
51
    protected $currentUrl;
52
53
    /**
54
     * Path to directory to store cookie file
55
     * @var string
56
     */
57
    protected $cookiesPath;
58
59
    public function __construct(Cookies $cookies)
60
    {
61
        $this->cookies = $cookies;
62
    }
63
64
    /**
65
     * Load cookies for a specified username. If a username is empty
66
     * we use a common file for all the anonymous requests.
67
     *
68
     * @param string $username
69
     * @return HttpClient
70
     */
71
    public function loadCookies($username = '')
72
    {
73
        return $this
74
            ->initCookieJar($username)
75
            ->fillCookies();
76
    }
77
78
    /**
79
     * Executes curl request.
80
     *
81
     * @param string $url
82
     * @param string $postString
83
     * @param array $headers
84
     * @return string
85
     */
86
    public function execute($url, $postString = '', array $headers = [])
87
    {
88
        return $this
89
            ->init($url, $postString, $headers)
90
            ->callCurl();
91
    }
92
93
    /**
94
     * @return mixed
95
     */
96
    protected function callCurl()
97
    {
98
        $result = curl_exec($this->curl);
99
100
        $this->currentUrl = curl_getinfo($this->curl, CURLINFO_EFFECTIVE_URL);
101
102
        curl_close($this->curl);
103
104
        $this->fillCookies();
105
106
        return $result;
107
    }
108
109
    /**
110
     * Initializes curl resource with options.
111
     *
112
     * @param string $url
113
     * @param string $postString
114
     * @param array $headers
115
     * @return $this
116
     */
117
    protected function init($url, $postString, $headers)
118
    {
119
        $this->headers = $headers;
120
121
        $this->curl = curl_init($url);
122
123
        if (empty($this->cookieJar)) {
124
            $this->loadCookies();
125
        }
126
127
        curl_setopt_array($this->curl, $this->makeHttpOptions($postString));
128
129
        return $this;
130
    }
131
132
    /**
133
     * @return array
134
     */
135
    protected function getDefaultHttpOptions()
136
    {
137
        return [
138
            CURLOPT_REFERER        => UrlBuilder::URL_BASE,
139
            CURLOPT_ENCODING       => 'gzip,deflate,br',
140
            CURLOPT_FRESH_CONNECT  => true,
141
            CURLOPT_HTTPHEADER     => $this->headers,
142
            CURLOPT_COOKIEFILE     => $this->cookieJar,
143
            CURLOPT_COOKIEJAR      => $this->cookieJar,
144
            CURLOPT_RETURNTRANSFER => true,
145
            CURLOPT_SSL_VERIFYPEER => false,
146
            CURLOPT_FOLLOWLOCATION => true,
147
        ];
148
    }
149
150
    /**
151
     * Adds necessary curl options for query.
152
     *
153
     * @param string $postString POST query string
154
     *
155
     * @return array
156
     */
157
    protected function makeHttpOptions($postString = '')
158
    {
159
        // Union custom Curl options and default ones.
160
        $options = array_replace(
161
            $this->options,
162
            $this->getDefaultHttpOptions()
163
        );
164
165
        if (!empty($postString)) {
166
            $options[CURLOPT_POST] = true;
167
            $options[CURLOPT_POSTFIELDS] = $postString;
168
        }
169
170
        return $options;
171
    }
172
173
    /**
174
     * Set custom Curl options to override default
175
     *
176
     * @codeCoverageIgnore
177
     * @param array $options
178
     * @return HttpClient
179
     */
180
    public function setOptions(array $options)
181
    {
182
        $this->options = $options;
183
184
        return $this;
185
    }
186
187
    /**
188
     * Get a cookie value by name
189
     *
190
     * @param $name
191
     * @return mixed
192
     */
193
    public function cookie($name)
194
    {
195
        return $this->cookies->get($name);
196
    }
197
198
    /**
199
     * Get all cookies
200
     *
201
     * @return array
202
     */
203
    public function cookies()
204
    {
205
        return $this->cookies->all();
206
    }
207
208
    /**
209
     * Set directory to store all cookie files.
210
     *
211
     * @codeCoverageIgnore
212
     * @param string $path
213
     * @return $this
214
     */
215
    public function setCookiesPath($path)
216
    {
217
        $this->cookiesPath = $path;
218
219
        return $this;
220
    }
221
222
    /**
223
     * @return $this
224
     */
225
    public function removeCookies()
226
    {
227
        if (file_exists($this->cookieJar)) {
228
            unlink($this->cookieJar);
229
        }
230
231
        $this->cookieJar = null;
232
233
        return $this;
234
    }
235
236
    /**
237
     * @param $username
238
     * @return $this
239
     */
240
    protected function initCookieJar($username)
241
    {
242
        $this->cookieJar = $this->initCookieFile($username);
243
244
        return $this;
245
    }
246
247
    /**
248
     * Returns cookie file name according to the provided username.
249
     *
250
     * @param string $username
251
     * @return string
252
     */
253
    protected function initCookieFile($username)
254
    {
255
        $cookieName = self::COOKIE_PREFIX . $username;
256
        $cookieFilePath = $this->getCookiesPath() . DIRECTORY_SEPARATOR . $cookieName;
257
258
        if (!file_exists($cookieFilePath)) {
259
            touch($cookieFilePath);
260
        }
261
262
        return $cookieFilePath;
263
    }
264
265
    /**
266
     * @return string
267
     */
268
    public function getCookiesPath()
269
    {
270
        return $this->cookiesPath ? : sys_get_temp_dir();
271
    }
272
273
    /**
274
     * @return $this
275
     */
276
    protected function fillCookies()
277
    {
278
        if (!empty($this->cookieJar)) {
279
            $this->cookies->fill($this->cookieJar);
280
        }
281
282
        return $this;
283
    }
284
285
    /**
286
     * @codeCoverageIgnore
287
     * @return string
288
     */
289
    public function getCurrentUrl()
290
    {
291
        return $this->currentUrl;
292
    }
293
294
    /**
295
     * @param string $host '192.168.1.1'
296
     * @param string $port '12345'
297
     * @param string $auth Authentication string: 'username:password'
298
     * @param string $type HTTP|SOCKS
299
     * @return HttpClient
300
     */
301
    public function useProxy($host, $port, $auth = null, $type = null)
302
    {
303
        $proxy = [
304
            CURLOPT_PROXY     => $host,
305
            CURLOPT_PROXYPORT => $port,
306
            CURLOPT_PROXYTYPE => $type ?: CURLPROXY_HTTP,
307
        ];
308
309
        if (null !== $auth) {
310
            $proxy[CURLOPT_PROXYUSERPWD] = $auth;
311
        }
312
313
        return $this->setOptions($proxy);
314
    }
315
316
    public function dontUseProxy()
317
    {
318
        unset(
319
            $this->options[CURLOPT_PROXY],
320
            $this->options[CURLOPT_PROXYPORT],
321
            $this->options[CURLOPT_PROXYTYPE],
322
            $this->options[CURLOPT_PROXYUSERPWD]
323
        );
324
325
        return $this;
326
    }
327
328
    /**
329
     * @return bool
330
     */
331
    public function usesProxy()
332
    {
333
        return isset($this->options[CURLOPT_PROXY]);
334
    }
335
336
    /**
337
     * @codeCoverageIgnore
338
     * @param string $host
339
     * @param string $port
340
     * @param null $auth
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $auth is correct as it would always require null to be passed?
Loading history...
341
     * @return HttpClient
342
     */
343
    public function useSocksProxy($host, $port, $auth = null)
344
    {
345
        return $this->useProxy($host, $port, CURLPROXY_SOCKS5, $auth);
346
    }
347
}
348