Completed
Pull Request — master (#19)
by Sergey
03:17
created

Request   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 224
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 3

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 20
c 1
b 0
f 0
lcom 1
cbo 3
dl 0
loc 224
rs 10

12 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
A followMethodCall() 0 18 2
A checkLoggedIn() 0 8 2
A exec() 0 12 1
A makeHttpOptions() 0 16 3
A clearToken() 0 4 1
A setLoggedIn() 0 7 2
A isLoggedIn() 0 5 1
A createRequestData() 0 17 3
A createEmptyRequestData() 0 4 1
A getDefaultHttpOptions() 0 16 1
A getDefaultHttpHeaders() 0 4 1
1
<?php
2
3
namespace seregazhuk\PinterestBot\Api;
4
5
use seregazhuk\PinterestBot\Interfaces\HttpInterface;
6
use seregazhuk\PinterestBot\Helpers\UrlHelper;
7
use seregazhuk\PinterestBot\Interfaces\RequestInterface;
8
use seregazhuk\PinterestBot\Helpers\CsrfHelper;
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 PINNER_ENTITY_ID   = 'user_id';
25
26
    protected $userAgent = 'Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Firefox/31.0';
27
    const COOKIE_NAME = 'pinterest_cookie';
28
    /**
29
     * @var Http
30
     */
31
    protected $http;
32
    protected $loggedIn;
33
    protected $cookieJar;
34
35
    public    $csrfToken = "";
36
37
    /**
38
     * Common headers needed for every query
39
     *
40
     * @var array
41
     */
42
    protected $requestHeaders = [
43
        'Host: www.pinterest.com',
44
        'Accept: application/json, text/javascript, */*; q=0.01',
45
        'Accept-Language: en-US,en;q=0.5',
46
        'DNT: 1',
47
        'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
48
        'X-Pinterest-AppState: active',
49
        'X-NEW-APP: 1',
50
        'X-APP-VERSION: 04cf8cc',
51
        'X-Requested-With: XMLHttpRequest',
52
    ];
53
54
    /**
55
     * @param HttpInterface $http
56
     */
57
    public function __construct(HttpInterface $http)
58
    {
59
        $this->http = $http;
0 ignored issues
show
Documentation Bug introduced by
$http is of type object<seregazhuk\Pinter...terfaces\HttpInterface>, but the property $http was declared to be of type object<seregazhuk\PinterestBot\Api\Http>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
60
        $this->cookieJar = self::COOKIE_NAME;
61
62
        if (file_exists($this->cookieJar)) {
63
            $this->setLoggedIn();
64
        }
65
    }
66
67
    /**
68
     * Executes api call for follow or unfollow user
69
     *
70
     * @param int    $entityId
71
     * @param string $entityName
72
     * @param string $url
73
     * @return bool
74
     */
75
    public function followMethodCall($entityId, $entityName, $url)
76
    {
77
        $dataJson = [
78
            "options" => [
79
                $entityName => $entityId,
80
            ],
81
            "context" => [],
82
        ];
83
84
        if ($entityName == self::INTEREST_ENTITY_ID) {
85
            $dataJson["options"]["interest_list"] = "favorited";
86
        }
87
88
        $post = ["data" => json_encode($dataJson, JSON_FORCE_OBJECT)];
89
        $postString = UrlHelper::buildRequestString($post);
90
91
        return $this->exec($url, $postString);
92
    }
93
94
    /**
95
     * Checks if bot is logged in
96
     *
97
     * @throws \LogicException if is not logged in
98
     * @return bool
99
     */
100
    public function checkLoggedIn()
101
    {
102
        if ( ! $this->loggedIn) {
103
            throw new \LogicException("You must log in before.");
104
        }
105
106
        return true;
107
    }
108
109
    /**
110
     * Executes request to Pinterest API
111
     *
112
     * @param string $resourceUrl
113
     * @param string $postString
114
     * @return array
115
     */
116
    public function exec($resourceUrl, $postString = "")
117
    {
118
        $url = UrlHelper::buildApiUrl($resourceUrl);
119
        $options = $this->makeHttpOptions($postString);
120
        $this->http->init($url);
121
        $this->http->setOptions($options);
122
123
        $res = $this->http->execute();
124
        $this->http->close();
125
126
        return json_decode($res, true);
127
    }
128
129
    /**
130
     * Adds necessary curl options for query
131
     *
132
     * @param string $postString POST query string
133
     * @return array
134
     */
135
    protected function makeHttpOptions($postString = "")
136
    {
137
        $options = $this->getDefaultHttpOptions();
138
139
        if ($this->csrfToken == CsrfHelper::DEFAULT_TOKEN) {
140
            $options[CURLOPT_REFERER] = UrlHelper::LOGIN_REF_URL;
141
            $headers[] = CsrfHelper::getDefaultCookie();
0 ignored issues
show
Coding Style Comprehensibility introduced by
$headers was never initialized. Although not strictly required by PHP, it is generally a good practice to add $headers = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
142
        }
143
144
        if ( ! empty($postString)) {
145
            $options[CURLOPT_POST] = true;
146
            $options[CURLOPT_POSTFIELDS] = $postString;
147
        }
148
149
        return $options;
150
    }
151
152
    /**
153
     * Clear token information
154
     *
155
     * @return mixed
156
     */
157
    public function clearToken()
158
    {
159
        $this->csrfToken = CsrfHelper::DEFAULT_TOKEN;
160
    }
161
162
    /**
163
     * Mark api as logged
164
     */
165
    public function setLoggedIn()
166
    {
167
        $this->csrfToken = CsrfHelper::getTokenFromFile($this->cookieJar);
168
        if ( ! empty($this->csrfToken)) {
169
            $this->loggedIn = true;
170
        }
171
    }
172
173
    /**
174
     * Get log status
175
     *
176
     * @return bool
177
     */
178
    public function isLoggedIn()
179
    {
180
        echo "triger\n";
181
        return $this->loggedIn;
182
    }
183
184
    /**
185
     * @param array|object $data
186
     * @param string|null  $sourceUrl
187
     * @param array        $bookmarks
188
     * @return array
189
     */
190
    public static function createRequestData($data = [], $sourceUrl = '/', $bookmarks = [])
191
    {
192
        if (empty($data)) {
193
            $data = self::createEmptyRequestData();
194
        }
195
196
        if ( ! empty($bookmarks)) {
197
            $data["options"]["bookmarks"] = $bookmarks;
198
        }
199
200
        $data["context"] = new \stdClass();
201
202
        return [
203
            "source_url" => $sourceUrl,
204
            "data"       => json_encode($data),
205
        ];
206
    }
207
208
    /**
209
     * @return array
210
     */
211
    protected static function createEmptyRequestData()
212
    {
213
        return array('options' => []);
214
    }
215
216
    /**
217
     * @return array
218
     */
219
    protected function getDefaultHttpOptions()
220
    {
221
        $options = [
222
            CURLOPT_USERAGENT      => $this->userAgent,
223
            CURLOPT_RETURNTRANSFER => true,
224
            CURLOPT_SSL_VERIFYPEER => false,
225
            CURLOPT_FOLLOWLOCATION => true,
226
            CURLOPT_ENCODING       => 'gzip,deflate',
227
            CURLOPT_HTTPHEADER     => $this->getDefaultHttpHeaders(),
228
            CURLOPT_REFERER        => UrlHelper::URL_BASE,
229
            CURLOPT_COOKIEFILE     => $this->cookieJar,
230
            CURLOPT_COOKIEJAR      => $this->cookieJar,
231
        ];
232
233
        return $options;
234
    }
235
236
    /**
237
     * @return array
238
     */
239
    protected function getDefaultHttpHeaders()
240
    {
241
        return array_merge($this->requestHeaders, ['X-CSRFToken: '.$this->csrfToken]);
242
    }
243
}
244