Completed
Pull Request — master (#60)
by Sergey
03:32
created

Request::createQuery()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 3
nc 1
nop 3
1
<?php
2
3
namespace seregazhuk\PinterestBot\Api;
4
5
use seregazhuk\PinterestBot\Helpers\UrlHelper;
6
use seregazhuk\PinterestBot\Helpers\CsrfHelper;
7
use seregazhuk\PinterestBot\Contracts\HttpInterface;
8
use seregazhuk\PinterestBot\Contracts\RequestInterface;
9
10
/**
11
 * Class Request
12
 *
13
 * @package Pinterest
14
 * @property resource $ch
15
 * @property bool     $loggedIn
16
 * @property string   $userAgent
17
 * @property string   $csrfToken
18
 * @property string   $cookieJar
19
 */
20
class Request implements RequestInterface
21
{
22
    const INTEREST_ENTITY_ID = 'interest_id';
23
    const BOARD_ENTITY_ID = 'board_id';
24
    const COOKIE_NAME = 'pinterest_cookie';
25
    const PINNER_ENTITY_ID = 'user_id';
26
27
    protected $userAgent = 'Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0';
28
    /**
29
     * @var HttpInterface
30
     */
31
    protected $http;
32
    protected $loggedIn;
33
    protected $cookieJar;
34
    protected $options;
35
36
    public $csrfToken = "";
37
38
    /**
39
     * Common headers needed for every query
40
     *
41
     * @var array
42
     */
43
    protected $requestHeaders = [
44
        'Accept: application/json, text/javascript, */*; q=0.01',
45
        'Accept-Language: en-US,en;q=0.5',
46
        'DNT: 1',
47
        'Host: nl.pinterest.com',
48
        'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
49
        'X-Pinterest-AppState: active',
50
        'X-NEW-APP: 1',
51
        'X-APP-VERSION: 04cf8cc',
52
        'X-Requested-With: XMLHttpRequest',
53
    ];
54
55
    /**
56
     * @param HttpInterface $http
57
     * @param string|null $userAgent
58
     */
59
    public function __construct(HttpInterface $http, $userAgent = null)
60
    {
61
        $this->http = $http;
62
        if ($userAgent !== null) {
63
            $this->userAgent = $userAgent;
64
        }
65
        $this->cookieJar = self::COOKIE_NAME;
66
    }
67
68
    /**
69
     * Executes api call for follow or unfollow user
70
     *
71
     * @param int    $entityId
72
     * @param string $entityName
73
     * @param string $url
74
     * @return array
75
     */
76
    public function followMethodCall($entityId, $entityName, $url)
77
    {
78
        $dataJson = [
79
            "options" => [
80
                $entityName => $entityId,
81
            ],
82
            "context" => [],
83
        ];
84
85
        if ($entityName == self::INTEREST_ENTITY_ID) {
86
            $dataJson["options"]["interest_list"] = "favorited";
87
        }
88
89
        $post = ["data" => json_encode($dataJson, JSON_FORCE_OBJECT)];
90
        $postString = UrlHelper::buildRequestString($post);
91
92
        return $this->exec($url, $postString);
93
    }
94
95
    /**
96
     * Executes request to Pinterest API
97
     *
98
     * @param string $resourceUrl
99
     * @param string $postString
100
     * @return array
101
     */
102
    public function exec($resourceUrl, $postString = "")
103
    {
104
        $url = UrlHelper::buildApiUrl($resourceUrl);
105
        $this->makeHttpOptions($postString);
106
        $res = $this->http->execute($url, $this->options);
107
108
        $this->http->close();
109
        return json_decode($res, true);
110
    }
111
112
    /**
113
     * Adds necessary curl options for query
114
     *
115
     * @param string $postString POST query string
116
     * @return $this
117
     */
118
    protected function makeHttpOptions($postString = "")
119
    {
120
        $this->setDefaultHttpOptions();
121
122
        if ($this->csrfToken == CsrfHelper::DEFAULT_TOKEN) {
123
            $this->options = $this->addDefaultCsrfInfo($this->options);
124
        }
125
126
        if ( ! empty($postString)) {
127
            $this->options[CURLOPT_POST] = true;
128
            $this->options[CURLOPT_POSTFIELDS] = $postString;
129
        }
130
131
        return $this;
132
    }
133
134
    /**
135
     * Clear token information
136
     * @return $this
137
     */
138
    public function clearToken()
139
    {
140
        $this->csrfToken = CsrfHelper::DEFAULT_TOKEN;
141
142
        return $this;
143
    }
144
145
    /**
146
     * Mark api as logged
147
     *
148
     * @return $this
149
     */
150
    public function setLoggedIn()
151
    {
152
        $this->csrfToken = CsrfHelper::getTokenFromFile($this->cookieJar);
153
        if ( ! empty($this->csrfToken)) {
154
            $this->loggedIn = true;
155
        }
156
157
        return $this;
158
    }
159
160
    /**
161
     * Get log status
162
     *
163
     * @return bool
164
     */
165
    public function isLoggedIn()
166
    {
167
        return $this->loggedIn;
168
    }
169
170
    /**
171
     * Create request string
172
     *
173
     * @param array $data
174
     * @param string $sourceUrl
175
     * @param array $bookmarks
176
     * @return string
177
     */
178
    public static function createQuery(array $data = [], $sourceUrl = '/', $bookmarks = [])
179
    {
180
        $request = Request::createRequestData($data, $sourceUrl, $bookmarks);
181
182
        return UrlHelper::buildRequestString($request);
183
    }
184
185
    /**
186
     * @param array|object $data
187
     * @param string|null  $sourceUrl
188
     * @param array        $bookmarks
189
     * @return array
190
     */
191
    public static function createRequestData(array $data = [], $sourceUrl = '/', $bookmarks = [])
192
    {
193
        if (empty($data)) {
194
            $data = self::createEmptyRequestData();
195
        }
196
197
        if ( ! empty($bookmarks)) {
198
            $data["options"]["bookmarks"] = $bookmarks;
199
        }
200
201
        $data["context"] = new \stdClass();
202
203
        return [
204
            "source_url" => $sourceUrl,
205
            "data"       => json_encode($data),
206
        ];
207
    }
208
209
    /**
210
     * @return array
211
     */
212
    protected static function createEmptyRequestData()
213
    {
214
        return array('options' => []);
215
    }
216
217
    /**
218
     * @return array
219
     */
220
    protected function setDefaultHttpOptions()
221
    {
222
        $this->options = [
223
            CURLOPT_USERAGENT      => $this->userAgent,
224
            CURLOPT_RETURNTRANSFER => true,
225
            CURLOPT_SSL_VERIFYPEER => false,
226
            CURLOPT_FOLLOWLOCATION => true,
227
            CURLOPT_ENCODING       => 'gzip,deflate',
228
            CURLOPT_HTTPHEADER     => $this->getDefaultHttpHeaders(),
229
            CURLOPT_REFERER        => UrlHelper::URL_BASE,
230
            CURLOPT_COOKIEFILE     => $this->cookieJar,
231
            CURLOPT_COOKIEJAR      => $this->cookieJar,
232
        ];
233
    }
234
235
    /**
236
     * @return array
237
     */
238
    protected function getDefaultHttpHeaders()
239
    {
240
        return array_merge($this->requestHeaders, ['X-CSRFToken: '.$this->csrfToken]);
241
    }
242
243
    /**
244
     * @param array $options
245
     * @return mixed
246
     */
247
    protected function addDefaultCsrfInfo($options)
248
    {
249
        $options[CURLOPT_REFERER] = UrlHelper::URL_BASE;
250
        $options[CURLOPT_HTTPHEADER][] = CsrfHelper::getDefaultCookie();
251
252
        return $options;
253
    }
254
}
255