InstagramRequest::setAccessToken()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Maztech;
4
5
use Maztech\Authentication\AccessToken;
6
use Maztech\Url\InstagramUrlManipulator;
7
use Maztech\Http\RequestBodyUrlEncoded;
8
use Maztech\Exceptions\InstagramSDKException;
9
10
/**
11
 * Class Request
12
 *
13
 * @package Instagram
14
 */
15
class InstagramRequest
16
{
17
    /**
18
     * @var InstagramApp The Instagram app entity.
19
     */
20
    protected $app;
21
22
    /**
23
     * @var string|null The access token to use for this request.
24
     */
25
    protected $accessToken;
26
27
    /**
28
     * @var string The HTTP method for this request.
29
     */
30
    protected $method;
31
32
    /**
33
     * @var string The Graph endpoint for this request.
34
     */
35
    protected $endpoint;
36
37
    /**
38
     * @var array The headers to send with this request.
39
     */
40
    protected $headers = [];
41
42
    /**
43
     * @var array The parameters to send with this request.
44
     */
45
    protected $params = [];
46
47
    /**
48
     * @var array The files to send with this request.
49
     */
50
    protected $files = [];
51
52
    /**
53
     * @var string ETag to send with this request.
54
     */
55
    protected $eTag;
56
57
    /**
58
     * Creates a new Request entity.
59
     *
60
     * @param InstagramApp|null        $app
61
     * @param AccessToken|string|null $accessToken
62
     * @param string|null             $method
63
     * @param string|null             $endpoint
64
     * @param array|null              $params
65
     * @param string|null             $eTag
66
     */
67
    public function __construct(InstagramApp $app = null, $accessToken = null, $method = null, $endpoint = null, array $params = [], $eTag = null)
68
    {
69
        $this->setApp($app);
70
        $this->setAccessToken($accessToken);
71
        $this->setMethod($method);
72
        $this->setEndpoint($endpoint);
73
        $this->setParams($params);
74
        $this->setETag($eTag);
75
    }
76
77
    /**
78
     * Set the access token for this request.
79
     *
80
     * @param AccessToken|string|null
81
     *
82
     * @return InstagramRequest
83
     */
84
    public function setAccessToken($accessToken)
85
    {
86
        $this->accessToken = $accessToken;
87
        if ($accessToken instanceof AccessToken) {
88
            $this->accessToken = $accessToken->getValue();
89
        }
90
91
        return $this;
92
    }
93
94
    /**
95
     * Sets the access token with one harvested from a URL or POST params.
96
     *
97
     * @param string $accessToken The access token.
98
     *
99
     * @return InstagramRequest
100
     *
101
     * @throws InstagramSDKException
102
     */
103
    public function setAccessTokenFromParams($accessToken)
104
    {
105
        $existingAccessToken = $this->getAccessToken();
106
        if (!$existingAccessToken) {
107
            $this->setAccessToken($accessToken);
108
        } elseif ($accessToken !== $existingAccessToken) {
109
            throw new InstagramSDKException('Access token mismatch. The access token provided in the InstagramRequest and the one provided in the URL or POST params do not match.');
110
        }
111
112
        return $this;
113
    }
114
115
    /**
116
     * Return the access token for this request.
117
     *
118
     * @return string|null
119
     */
120
    public function getAccessToken()
121
    {
122
        return $this->accessToken;
123
    }
124
125
    /**
126
     * Return the access token for this request as an AccessToken entity.
127
     *
128
     * @return AccessToken|null
129
     */
130
    public function getAccessTokenEntity()
131
    {
132
        return $this->accessToken ? new AccessToken($this->accessToken) : null;
133
    }
134
135
    /**
136
     * Set the InstagramApp entity used for this request.
137
     *
138
     * @param InstagramApp|null $app
139
     */
140
    public function setApp(InstagramApp $app = null)
141
    {
142
        $this->app = $app;
143
    }
144
145
    /**
146
     * Return the InstagramApp entity used for this request.
147
     *
148
     * @return InstagramApp
149
     */
150
    public function getApp()
151
    {
152
        return $this->app;
153
    }
154
155
    /**
156
     * Generate an app secret proof to sign this request.
157
     *
158
     * @return string|null
159
     */
160
    public function getAppSecretProof()
161
    {
162
        if (!$accessTokenEntity = $this->getAccessTokenEntity()) {
163
            return null;
164
        }
165
166
        return $accessTokenEntity->getAppSecretProof($this->app->getSecret());
167
    }
168
169
    /**
170
     * Validate that an access token exists for this request.
171
     *
172
     * @throws InstagramSDKException
173
     */
174
    public function validateAccessToken()
175
    {
176
        $accessToken = $this->getAccessToken();
177
        if (!$accessToken) {
178
            throw new InstagramSDKException('You must provide an access token.');
179
        }
180
    }
181
182
    /**
183
     * Set the HTTP method for this request.
184
     *
185
     * @param string
186
     */
187
    public function setMethod($method)
188
    {
189
        $this->method = strtoupper($method);
190
    }
191
192
    /**
193
     * Return the HTTP method for this request.
194
     *
195
     * @return string
196
     */
197
    public function getMethod()
198
    {
199
        return $this->method;
200
    }
201
202
    /**
203
     * Validate that the HTTP method is set.
204
     *
205
     * @throws InstagramSDKException
206
     */
207
    public function validateMethod()
208
    {
209
        if (!$this->method) {
210
            throw new InstagramSDKException('HTTP method not specified.');
211
        }
212
213
        if (!in_array($this->method, ['GET', 'POST', 'DELETE'])) {
214
            throw new InstagramSDKException('Invalid HTTP method specified.');
215
        }
216
    }
217
218
    /**
219
     * Set the endpoint for this request.
220
     *
221
     * @param string
222
     *
223
     * @return InstagramRequest
224
     *
225
     * @throws InstagramSDKException
226
     */
227
    public function setEndpoint($endpoint)
228
    {
229
        // Harvest the access token from the endpoint to keep things in sync
230
        $params = InstagramUrlManipulator::getParamsAsArray($endpoint);
231
        if (isset($params['access_token'])) {
232
            $this->setAccessTokenFromParams($params['access_token']);
233
        }
234
235
        // Clean the token & app secret proof from the endpoint.
236
        $filterParams = ['access_token', 'appsecret_proof'];
237
        $this->endpoint = InstagramUrlManipulator::removeParamsFromUrl($endpoint, $filterParams);
238
239
        return $this;
240
    }
241
242
    /**
243
     * Return the endpoint for this request.
244
     *
245
     * @return string
246
     */
247
    public function getEndpoint()
248
    {
249
        // For batch requests, this will be empty
250
        return $this->endpoint;
251
    }
252
253
    /**
254
     * Generate and return the headers for this request.
255
     *
256
     * @return array
257
     */
258
    public function getHeaders()
259
    {
260
        $headers = static::getDefaultHeaders();
261
262
        if ($this->eTag) {
263
            $headers['If-None-Match'] = $this->eTag;
264
        }
265
266
        return array_merge($this->headers, $headers);
267
    }
268
269
    /**
270
     * Set the headers for this request.
271
     *
272
     * @param array $headers
273
     */
274
    public function setHeaders(array $headers)
275
    {
276
        $this->headers = array_merge($this->headers, $headers);
277
    }
278
279
    /**
280
     * Sets the eTag value.
281
     *
282
     * @param string $eTag
283
     */
284
    public function setETag($eTag)
285
    {
286
        $this->eTag = $eTag;
287
    }
288
289
    /**
290
     * Set the params for this request.
291
     *
292
     * @param array $params
293
     *
294
     * @return InstagramRequest
295
     *
296
     * @throws InstagramSDKException
297
     */
298
    public function setParams(array $params = [])
299
    {
300
        if (isset($params['access_token'])) {
301
            $this->setAccessTokenFromParams($params['access_token']);
302
        }
303
304
        // Don't let these buggers slip in.
305
        unset($params['access_token'], $params['appsecret_proof']);
306
307
        // @TODO Refactor code above with this
308
        //$params = $this->sanitizeAuthenticationParams($params)
309
        $this->dangerouslySetParams($params);
310
311
        return $this;
312
    }
313
314
    /**
315
     * Set the params for this request without filtering them first.
316
     *
317
     * @param array $params
318
     *
319
     * @return InstagramRequest
320
     */
321
    public function dangerouslySetParams(array $params = [])
322
    {
323
        $this->params = array_merge($this->params, $params);
324
325
        return $this;
326
    }
327
328
    /**
329
     * Returns the body of the request as URL-encoded.
330
     *
331
     * @return RequestBodyUrlEncoded
332
     */
333
    public function getUrlEncodedBody()
334
    {
335
        $params = $this->getPostParams();
336
337
        return new RequestBodyUrlEncoded($params);
338
    }
339
340
    /**
341
     * Generate and return the params for this request.
342
     *
343
     * @return array
344
     */
345
    public function getParams()
346
    {
347
        $params = $this->params;
348
349
        $accessToken = $this->getAccessToken();
350
        if ($accessToken) {
351
            $params['access_token'] = $accessToken;
352
            $params['appsecret_proof'] = $this->getAppSecretProof();
353
        }
354
355
        return $params;
356
    }
357
358
    /**
359
     * Only return params on POST requests.
360
     *
361
     * @return array
362
     */
363
    public function getPostParams()
364
    {
365
        if ($this->getMethod() === 'POST') {
366
            return $this->getParams();
367
        }
368
369
        return [];
370
    }
371
372
    /**
373
     * Generate and return the URL for this request.
374
     *
375
     * @return string
376
     */
377
    public function getUrl()
378
    {
379
        $this->validateMethod();
380
381
        $endpoint = InstagramUrlManipulator::forceSlashPrefix($this->getEndpoint());
382
383
        $url = $endpoint;
384
385
        if ($this->getMethod() !== 'POST') {
386
            $params = $this->getParams();
387
            $url = InstagramUrlManipulator::appendParamsToUrl($url, $params);
388
        }
389
390
        return $url;
391
    }
392
393
    /**
394
     * Return the default headers that every request should use.
395
     *
396
     * @return array
397
     */
398
    public static function getDefaultHeaders()
399
    {
400
        return [
401
            'User-Agent' => 'fb-php-' . Instagram::VERSION,
402
            'Accept-Encoding' => '*',
403
        ];
404
    }
405
}
406