Subversion Repositories cheapmusic

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
25 - 1
<?php
2
/**
3
 * Copyright 2017 Facebook, Inc.
4
 *
5
 * You are hereby granted a non-exclusive, worldwide, royalty-free license to
6
 * use, copy, modify, and distribute this software in source code or binary
7
 * form for use in connection with the web services and APIs provided by
8
 * Facebook.
9
 *
10
 * As with any software that integrates with the Facebook platform, your use
11
 * of this software is subject to the Facebook Developer Principles and
12
 * Policies [http://developers.facebook.com/policy/]. This copyright notice
13
 * shall be included in all copies or substantial portions of the software.
14
 *
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 * DEALINGS IN THE SOFTWARE.
22
 *
23
 */
24
namespace Facebook;
25
 
26
use Facebook\Authentication\AccessToken;
27
use Facebook\Url\FacebookUrlManipulator;
28
use Facebook\FileUpload\FacebookFile;
29
use Facebook\FileUpload\FacebookVideo;
30
use Facebook\Http\RequestBodyMultipart;
31
use Facebook\Http\RequestBodyUrlEncoded;
32
use Facebook\Exceptions\FacebookSDKException;
33
 
34
/**
35
 * Class Request
36
 *
37
 * @package Facebook
38
 */
39
class FacebookRequest
40
{
41
    /**
42
     * @var FacebookApp The Facebook app entity.
43
     */
44
    protected $app;
45
 
46
    /**
47
     * @var string|null The access token to use for this request.
48
     */
49
    protected $accessToken;
50
 
51
    /**
52
     * @var string The HTTP method for this request.
53
     */
54
    protected $method;
55
 
56
    /**
57
     * @var string The Graph endpoint for this request.
58
     */
59
    protected $endpoint;
60
 
61
    /**
62
     * @var array The headers to send with this request.
63
     */
64
    protected $headers = [];
65
 
66
    /**
67
     * @var array The parameters to send with this request.
68
     */
69
    protected $params = [];
70
 
71
    /**
72
     * @var array The files to send with this request.
73
     */
74
    protected $files = [];
75
 
76
    /**
77
     * @var string ETag to send with this request.
78
     */
79
    protected $eTag;
80
 
81
    /**
82
     * @var string Graph version to use for this request.
83
     */
84
    protected $graphVersion;
85
 
86
    /**
87
     * Creates a new Request entity.
88
     *
89
     * @param FacebookApp|null        $app
90
     * @param AccessToken|string|null $accessToken
91
     * @param string|null             $method
92
     * @param string|null             $endpoint
93
     * @param array|null              $params
94
     * @param string|null             $eTag
95
     * @param string|null             $graphVersion
96
     */
97
    public function __construct(FacebookApp $app = null, $accessToken = null, $method = null, $endpoint = null, array $params = [], $eTag = null, $graphVersion = null)
98
    {
99
        $this->setApp($app);
100
        $this->setAccessToken($accessToken);
101
        $this->setMethod($method);
102
        $this->setEndpoint($endpoint);
103
        $this->setParams($params);
104
        $this->setETag($eTag);
105
        $this->graphVersion = $graphVersion ?: Facebook::DEFAULT_GRAPH_VERSION;
106
    }
107
 
108
    /**
109
     * Set the access token for this request.
110
     *
111
     * @param AccessToken|string|null
112
     *
113
     * @return FacebookRequest
114
     */
115
    public function setAccessToken($accessToken)
116
    {
117
        $this->accessToken = $accessToken;
118
        if ($accessToken instanceof AccessToken) {
119
            $this->accessToken = $accessToken->getValue();
120
        }
121
 
122
        return $this;
123
    }
124
 
125
    /**
126
     * Sets the access token with one harvested from a URL or POST params.
127
     *
128
     * @param string $accessToken The access token.
129
     *
130
     * @return FacebookRequest
131
     *
132
     * @throws FacebookSDKException
133
     */
134
    public function setAccessTokenFromParams($accessToken)
135
    {
136
        $existingAccessToken = $this->getAccessToken();
137
        if (!$existingAccessToken) {
138
            $this->setAccessToken($accessToken);
139
        } elseif ($accessToken !== $existingAccessToken) {
140
            throw new FacebookSDKException('Access token mismatch. The access token provided in the FacebookRequest and the one provided in the URL or POST params do not match.');
141
        }
142
 
143
        return $this;
144
    }
145
 
146
    /**
147
     * Return the access token for this request.
148
     *
149
     * @return string|null
150
     */
151
    public function getAccessToken()
152
    {
153
        return $this->accessToken;
154
    }
155
 
156
    /**
157
     * Return the access token for this request as an AccessToken entity.
158
     *
159
     * @return AccessToken|null
160
     */
161
    public function getAccessTokenEntity()
162
    {
163
        return $this->accessToken ? new AccessToken($this->accessToken) : null;
164
    }
165
 
166
    /**
167
     * Set the FacebookApp entity used for this request.
168
     *
169
     * @param FacebookApp|null $app
170
     */
171
    public function setApp(FacebookApp $app = null)
172
    {
173
        $this->app = $app;
174
    }
175
 
176
    /**
177
     * Return the FacebookApp entity used for this request.
178
     *
179
     * @return FacebookApp
180
     */
181
    public function getApp()
182
    {
183
        return $this->app;
184
    }
185
 
186
    /**
187
     * Generate an app secret proof to sign this request.
188
     *
189
     * @return string|null
190
     */
191
    public function getAppSecretProof()
192
    {
193
        if (!$accessTokenEntity = $this->getAccessTokenEntity()) {
194
            return null;
195
        }
196
 
197
        return $accessTokenEntity->getAppSecretProof($this->app->getSecret());
198
    }
199
 
200
    /**
201
     * Validate that an access token exists for this request.
202
     *
203
     * @throws FacebookSDKException
204
     */
205
    public function validateAccessToken()
206
    {
207
        $accessToken = $this->getAccessToken();
208
        if (!$accessToken) {
209
            throw new FacebookSDKException('You must provide an access token.');
210
        }
211
    }
212
 
213
    /**
214
     * Set the HTTP method for this request.
215
     *
216
     * @param string
217
     */
218
    public function setMethod($method)
219
    {
220
        $this->method = strtoupper($method);
221
    }
222
 
223
    /**
224
     * Return the HTTP method for this request.
225
     *
226
     * @return string
227
     */
228
    public function getMethod()
229
    {
230
        return $this->method;
231
    }
232
 
233
    /**
234
     * Validate that the HTTP method is set.
235
     *
236
     * @throws FacebookSDKException
237
     */
238
    public function validateMethod()
239
    {
240
        if (!$this->method) {
241
            throw new FacebookSDKException('HTTP method not specified.');
242
        }
243
 
244
        if (!in_array($this->method, ['GET', 'POST', 'DELETE'])) {
245
            throw new FacebookSDKException('Invalid HTTP method specified.');
246
        }
247
    }
248
 
249
    /**
250
     * Set the endpoint for this request.
251
     *
252
     * @param string
253
     *
254
     * @return FacebookRequest
255
     *
256
     * @throws FacebookSDKException
257
     */
258
    public function setEndpoint($endpoint)
259
    {
260
        // Harvest the access token from the endpoint to keep things in sync
261
        $params = FacebookUrlManipulator::getParamsAsArray($endpoint);
262
        if (isset($params['access_token'])) {
263
            $this->setAccessTokenFromParams($params['access_token']);
264
        }
265
 
266
        // Clean the token & app secret proof from the endpoint.
267
        $filterParams = ['access_token', 'appsecret_proof'];
268
        $this->endpoint = FacebookUrlManipulator::removeParamsFromUrl($endpoint, $filterParams);
269
 
270
        return $this;
271
    }
272
 
273
    /**
274
     * Return the endpoint for this request.
275
     *
276
     * @return string
277
     */
278
    public function getEndpoint()
279
    {
280
        // For batch requests, this will be empty
281
        return $this->endpoint;
282
    }
283
 
284
    /**
285
     * Generate and return the headers for this request.
286
     *
287
     * @return array
288
     */
289
    public function getHeaders()
290
    {
291
        $headers = static::getDefaultHeaders();
292
 
293
        if ($this->eTag) {
294
            $headers['If-None-Match'] = $this->eTag;
295
        }
296
 
297
        return array_merge($this->headers, $headers);
298
    }
299
 
300
    /**
301
     * Set the headers for this request.
302
     *
303
     * @param array $headers
304
     */
305
    public function setHeaders(array $headers)
306
    {
307
        $this->headers = array_merge($this->headers, $headers);
308
    }
309
 
310
    /**
311
     * Sets the eTag value.
312
     *
313
     * @param string $eTag
314
     */
315
    public function setETag($eTag)
316
    {
317
        $this->eTag = $eTag;
318
    }
319
 
320
    /**
321
     * Set the params for this request.
322
     *
323
     * @param array $params
324
     *
325
     * @return FacebookRequest
326
     *
327
     * @throws FacebookSDKException
328
     */
329
    public function setParams(array $params = [])
330
    {
331
        if (isset($params['access_token'])) {
332
            $this->setAccessTokenFromParams($params['access_token']);
333
        }
334
 
335
        // Don't let these buggers slip in.
336
        unset($params['access_token'], $params['appsecret_proof']);
337
 
338
        // @TODO Refactor code above with this
339
        //$params = $this->sanitizeAuthenticationParams($params);
340
        $params = $this->sanitizeFileParams($params);
341
        $this->dangerouslySetParams($params);
342
 
343
        return $this;
344
    }
345
 
346
    /**
347
     * Set the params for this request without filtering them first.
348
     *
349
     * @param array $params
350
     *
351
     * @return FacebookRequest
352
     */
353
    public function dangerouslySetParams(array $params = [])
354
    {
355
        $this->params = array_merge($this->params, $params);
356
 
357
        return $this;
358
    }
359
 
360
    /**
361
     * Iterate over the params and pull out the file uploads.
362
     *
363
     * @param array $params
364
     *
365
     * @return array
366
     */
367
    public function sanitizeFileParams(array $params)
368
    {
369
        foreach ($params as $key => $value) {
370
            if ($value instanceof FacebookFile) {
371
                $this->addFile($key, $value);
372
                unset($params[$key]);
373
            }
374
        }
375
 
376
        return $params;
377
    }
378
 
379
    /**
380
     * Add a file to be uploaded.
381
     *
382
     * @param string       $key
383
     * @param FacebookFile $file
384
     */
385
    public function addFile($key, FacebookFile $file)
386
    {
387
        $this->files[$key] = $file;
388
    }
389
 
390
    /**
391
     * Removes all the files from the upload queue.
392
     */
393
    public function resetFiles()
394
    {
395
        $this->files = [];
396
    }
397
 
398
    /**
399
     * Get the list of files to be uploaded.
400
     *
401
     * @return array
402
     */
403
    public function getFiles()
404
    {
405
        return $this->files;
406
    }
407
 
408
    /**
409
     * Let's us know if there is a file upload with this request.
410
     *
411
     * @return boolean
412
     */
413
    public function containsFileUploads()
414
    {
415
        return !empty($this->files);
416
    }
417
 
418
    /**
419
     * Let's us know if there is a video upload with this request.
420
     *
421
     * @return boolean
422
     */
423
    public function containsVideoUploads()
424
    {
425
        foreach ($this->files as $file) {
426
            if ($file instanceof FacebookVideo) {
427
                return true;
428
            }
429
        }
430
 
431
        return false;
432
    }
433
 
434
    /**
435
     * Returns the body of the request as multipart/form-data.
436
     *
437
     * @return RequestBodyMultipart
438
     */
439
    public function getMultipartBody()
440
    {
441
        $params = $this->getPostParams();
442
 
443
        return new RequestBodyMultipart($params, $this->files);
444
    }
445
 
446
    /**
447
     * Returns the body of the request as URL-encoded.
448
     *
449
     * @return RequestBodyUrlEncoded
450
     */
451
    public function getUrlEncodedBody()
452
    {
453
        $params = $this->getPostParams();
454
 
455
        return new RequestBodyUrlEncoded($params);
456
    }
457
 
458
    /**
459
     * Generate and return the params for this request.
460
     *
461
     * @return array
462
     */
463
    public function getParams()
464
    {
465
        $params = $this->params;
466
 
467
        $accessToken = $this->getAccessToken();
468
        if ($accessToken) {
469
            $params['access_token'] = $accessToken;
470
            $params['appsecret_proof'] = $this->getAppSecretProof();
471
        }
472
 
473
        return $params;
474
    }
475
 
476
    /**
477
     * Only return params on POST requests.
478
     *
479
     * @return array
480
     */
481
    public function getPostParams()
482
    {
483
        if ($this->getMethod() === 'POST') {
484
            return $this->getParams();
485
        }
486
 
487
        return [];
488
    }
489
 
490
    /**
491
     * The graph version used for this request.
492
     *
493
     * @return string
494
     */
495
    public function getGraphVersion()
496
    {
497
        return $this->graphVersion;
498
    }
499
 
500
    /**
501
     * Generate and return the URL for this request.
502
     *
503
     * @return string
504
     */
505
    public function getUrl()
506
    {
507
        $this->validateMethod();
508
 
509
        $graphVersion = FacebookUrlManipulator::forceSlashPrefix($this->graphVersion);
510
        $endpoint = FacebookUrlManipulator::forceSlashPrefix($this->getEndpoint());
511
 
512
        $url = $graphVersion . $endpoint;
513
 
514
        if ($this->getMethod() !== 'POST') {
515
            $params = $this->getParams();
516
            $url = FacebookUrlManipulator::appendParamsToUrl($url, $params);
517
        }
518
 
519
        return $url;
520
    }
521
 
522
    /**
523
     * Return the default headers that every request should use.
524
     *
525
     * @return array
526
     */
527
    public static function getDefaultHeaders()
528
    {
529
        return [
530
            'User-Agent' => 'fb-php-' . Facebook::VERSION,
531
            'Accept-Encoding' => '*',
532
        ];
533
    }
534
}