Completed
Push — master ( 55e4bc...43c4e4 )
by Sergey
08:58 queued 05:00
created

CurlHttpClient::usesProxy()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
cc 1
eloc 2
nc 1
nop 0
rs 10
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 CurlAdapter.
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 specified username
66
     *
67
     * @param string $username
68
     * @return HttpClient
69
     */
70
    public function loadCookies($username = '')
71
    {
72
        return $this
73
            ->initCookieJar($username)
74
            ->fillCookies();
75
    }
76
77
    /**
78
     * Executes curl request.
79
     *
80
     * @param string $url
81
     * @param string $postString
82
     * @param array $headers
83
     * @return string
84
     */
85
    public function execute($url, $postString = '', array $headers = [])
86
    {
87
        return $this
88
            ->init($url, $postString, $headers)
89
            ->callCurl();
90
    }
91
92
    /**
93
     * @return mixed
94
     */
95
    protected function callCurl()
96
    {
97
        $result = curl_exec($this->curl);
98
99
        $this->currentUrl = curl_getinfo($this->curl, CURLINFO_EFFECTIVE_URL);
100
101
        curl_close($this->curl);
102
103
        $this->fillCookies();
104
105
        return $result;
106
    }
107
108
    /**
109
     * Initializes curl resource with options.
110
     *
111
     * @param string $url
112
     * @param string $postString
113
     * @param array $headers
114
     * @return $this
115
     */
116
    protected function init($url, $postString, $headers)
117
    {
118
        $this->headers = $headers;
119
120
        $this->curl = curl_init($url);
121
122
        if (empty($this->cookieJar)) {
123
            $this->loadCookies();
124
        }
125
126
        curl_setopt_array($this->curl, $this->makeHttpOptions($postString));
127
128
        return $this;
129
    }
130
131
    /**
132
     * @return array
133
     */
134
    protected function getDefaultHttpOptions()
135
    {
136
        return [
137
            CURLOPT_REFERER        => UrlBuilder::URL_BASE,
138
            CURLOPT_ENCODING       => 'gzip,deflate, br',
139
            CURLOPT_FRESH_CONNECT  => true,
140
            CURLOPT_COOKIEJAR      => $this->cookieJar,
141
            CURLOPT_HTTPHEADER     => $this->headers,
142
            CURLOPT_COOKIEFILE     => $this->cookieJar,
143
            CURLOPT_RETURNTRANSFER => true,
144
            CURLOPT_SSL_VERIFYPEER => false,
145
            CURLOPT_FOLLOWLOCATION => true,
146
        ];
147
    }
148
149
    /**
150
     * Adds necessary curl options for query.
151
     *
152
     * @param string $postString POST query string
153
     *
154
     * @return array
155
     */
156
    protected function makeHttpOptions($postString = '')
157
    {
158
        // Union custom Curl options and default ones.
159
        $options = array_replace(
160
            $this->options,
161
            $this->getDefaultHttpOptions()
162
        );
163
164
        if (!empty($postString)) {
165
            $options[CURLOPT_POST] = true;
166
            $options[CURLOPT_POSTFIELDS] = $postString;
167
        }
168
169
        return $options;
170
    }
171
172
    /**
173
     * Set custom Curl options to override default
174
     *
175
     * @codeCoverageIgnore
176
     * @param array $options
177
     * @return HttpClient
178
     */
179
    public function setOptions(array $options)
180
    {
181
        $this->options = $options;
182
183
        return $this;
184
    }
185
186
    /**
187
     * Get a cookie value by name
188
     *
189
     * @param $name
190
     * @return mixed
191
     */
192
    public function cookie($name)
193
    {
194
        return $this->cookies->get($name);
195
    }
196
197
    /**
198
     * Get all cookies
199
     *
200
     * @return array
201
     */
202
    public function cookies()
203
    {
204
        return $this->cookies->all();
205
    }
206
207
    /**
208
     * Set directory to store all cookie files.
209
     *
210
     * @codeCoverageIgnore
211
     * @param string $path
212
     * @return $this
213
     */
214
    public function setCookiesPath($path)
215
    {
216
        $this->cookiesPath = $path;
217
218
        return $this;
219
    }
220
221
    /**
222
     * @return $this
223
     */
224
    public function removeCookies()
225
    {
226
        if (file_exists($this->cookieJar)) {
227
            unlink($this->cookieJar);
228
        }
229
230
        $this->cookieJar = null;
231
232
        return $this;
233
    }
234
235
    /**
236
     * Init cookie file for a specified username. If username is empty we use
237
     * common cookie file for all sessions. If file does not exist it will
238
     * be created in system temp directory.
239
     *
240
     * @param $username
241
     * @return $this
242
     */
243
    protected function initCookieJar($username = '')
244
    {
245
        $this->cookieJar = $this->initCookieFile($username);
246
247
        return $this;
248
    }
249
250
    /**
251
     * Returns cookie file name by username. If username is empty we use a
252
     * random cookie name, to be sure we have different cookies
253
     * in parallel sessions.
254
     *
255
     * @param string $username
256
     * @return string
257
     */
258
    protected function initCookieFile($username = '')
259
    {
260
        if(empty($username)) {
261
            return tempnam($this->getCookiesPath(), self::COOKIE_PREFIX);
262
        }
263
264
        $cookieName = self::COOKIE_PREFIX . $username;
265
        $cookieFilePath = $this->getCookiesPath() . DIRECTORY_SEPARATOR . $cookieName;
266
267
        if (!file_exists($cookieFilePath)) {
268
            touch($cookieFilePath);
269
        }
270
271
        return $cookieFilePath;
272
    }
273
274
    /**
275
     * @return string
276
     */
277
    public function getCookiesPath()
278
    {
279
        return $this->cookiesPath ? : sys_get_temp_dir();
280
    }
281
282
    /**
283
     * @return $this
284
     */
285
    protected function fillCookies()
286
    {
287
        $this->cookies->fill($this->cookieJar);
288
289
        return $this;
290
    }
291
292
    /**
293
     * @codeCoverageIgnore
294
     * @return string
295
     */
296
    public function getCurrentUrl()
297
    {
298
        return $this->currentUrl;
299
    }
300
301
    /**
302
     * @param string $host '192.168.1.1'
303
     * @param string $port '12345'
304
     * @param string $auth Authentication string: 'username:password'
305
     * @param string $type HTTP|SOCKS
306
     * @return HttpClient
307
     */
308
    public function useProxy($host, $port, $auth = null, $type = null)
309
    {
310
        $proxy = [
311
            CURLOPT_PROXY     => $host,
312
            CURLOPT_PROXYPORT => $port,
313
            CURLOPT_PROXYTYPE => $type ? $type : CURLPROXY_HTTP,
314
        ];
315
316
        if($auth) $proxy[CURLOPT_PROXYUSERPWD] = $auth;
0 ignored issues
show
Bug Best Practice introduced by
The expression $auth of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
317
318
        return $this->setOptions($proxy);
319
    }
320
321
    public function dontUseProxy()
322
    {
323
        unset($this->options[CURLOPT_PROXY]);
324
        unset($this->options[CURLOPT_PROXYPORT]);
325
        unset($this->options[CURLOPT_PROXYTYPE]);
326
        unset($this->options[CURLOPT_PROXYUSERPWD]);
327
328
        return $this;
329
    }
330
331
    /**
332
     * @return bool
333
     */
334
    public function usesProxy()
335
    {
336
        return isset($this->options[CURLOPT_PROXY]);
337
    }
338
339
    /**
340
     * @codeCoverageIgnore
341
     * @param string $host
342
     * @param string $port
343
     * @param null $auth
344
     * @return HttpClient
345
     */
346
    public function useSocksProxy($host, $port, $auth = null)
347
    {
348
        return $this->useProxy($host, $port, CURLPROXY_SOCKS5, $auth);
349
    }
350
}