Completed
Pull Request — master (#230)
by Sergey
02:16
created

CurlHttpClient::setDebug()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

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