FacebookClient   A
last analyzed

Complexity

Total Complexity 19

Size/Duplication

Total Lines 215
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 10

Importance

Changes 0
Metric Value
dl 0
loc 215
rs 10
c 0
b 0
f 0
wmc 19
lcom 1
cbo 10

9 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 2
A setHttpClientHandler() 0 4 1
A getHttpClientHandler() 0 4 1
A detectHttpClientHandler() 0 4 2
A enableBetaMode() 0 4 1
A getBaseGraphUrl() 0 8 4
B prepareRequestMessage() 0 25 2
B sendRequest() 0 35 5
A sendBatchRequest() 0 7 1
1
<?php
2
/**
3
 * Copyright 2016 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\HttpClients\FacebookHttpClientInterface;
27
use Facebook\HttpClients\FacebookCurlHttpClient;
28
use Facebook\HttpClients\FacebookStreamHttpClient;
29
use Facebook\Exceptions\FacebookSDKException;
30
31
/**
32
 * Class FacebookClient
33
 *
34
 * @package Facebook
35
 */
36
class FacebookClient
37
{
38
    /**
39
     * @const string Production Graph API URL.
40
     */
41
    const BASE_GRAPH_URL = 'https://graph.facebook.com';
42
43
    /**
44
     * @const string Graph API URL for video uploads.
45
     */
46
    const BASE_GRAPH_VIDEO_URL = 'https://graph-video.facebook.com';
47
48
    /**
49
     * @const string Beta Graph API URL.
50
     */
51
    const BASE_GRAPH_URL_BETA = 'https://graph.beta.facebook.com';
52
53
    /**
54
     * @const string Beta Graph API URL for video uploads.
55
     */
56
    const BASE_GRAPH_VIDEO_URL_BETA = 'https://graph-video.beta.facebook.com';
57
58
    /**
59
     * @const int The timeout in seconds for a normal request.
60
     */
61
    const DEFAULT_REQUEST_TIMEOUT = 60;
62
63
    /**
64
     * @const int The timeout in seconds for a request that contains file uploads.
65
     */
66
    const DEFAULT_FILE_UPLOAD_REQUEST_TIMEOUT = 3600;
67
68
    /**
69
     * @const int The timeout in seconds for a request that contains video uploads.
70
     */
71
    const DEFAULT_VIDEO_UPLOAD_REQUEST_TIMEOUT = 7200;
72
73
    /**
74
     * @var bool Toggle to use Graph beta url.
75
     */
76
    protected $enableBetaMode = false;
77
78
    /**
79
     * @var FacebookHttpClientInterface HTTP client handler.
80
     */
81
    protected $httpClientHandler;
82
83
    /**
84
     * @var int The number of calls that have been made to Graph.
85
     */
86
    public static $requestCount = 0;
87
88
    /**
89
     * Instantiates a new FacebookClient object.
90
     *
91
     * @param FacebookHttpClientInterface|null $httpClientHandler
92
     * @param boolean                          $enableBeta
93
     */
94
    public function __construct(FacebookHttpClientInterface $httpClientHandler = null, $enableBeta = false)
95
    {
96
        $this->httpClientHandler = $httpClientHandler ?: $this->detectHttpClientHandler();
97
        $this->enableBetaMode = $enableBeta;
98
    }
99
100
    /**
101
     * Sets the HTTP client handler.
102
     *
103
     * @param FacebookHttpClientInterface $httpClientHandler
104
     */
105
    public function setHttpClientHandler(FacebookHttpClientInterface $httpClientHandler)
106
    {
107
        $this->httpClientHandler = $httpClientHandler;
108
    }
109
110
    /**
111
     * Returns the HTTP client handler.
112
     *
113
     * @return FacebookHttpClientInterface
114
     */
115
    public function getHttpClientHandler()
116
    {
117
        return $this->httpClientHandler;
118
    }
119
120
    /**
121
     * Detects which HTTP client handler to use.
122
     *
123
     * @return FacebookHttpClientInterface
124
     */
125
    public function detectHttpClientHandler()
126
    {
127
        return extension_loaded('curl') ? new FacebookCurlHttpClient() : new FacebookStreamHttpClient();
128
    }
129
130
    /**
131
     * Toggle beta mode.
132
     *
133
     * @param boolean $betaMode
134
     */
135
    public function enableBetaMode($betaMode = true)
136
    {
137
        $this->enableBetaMode = $betaMode;
138
    }
139
140
    /**
141
     * Returns the base Graph URL.
142
     *
143
     * @param boolean $postToVideoUrl Post to the video API if videos are being uploaded.
144
     *
145
     * @return string
146
     */
147
    public function getBaseGraphUrl($postToVideoUrl = false)
148
    {
149
        if ($postToVideoUrl) {
150
            return $this->enableBetaMode ? static::BASE_GRAPH_VIDEO_URL_BETA : static::BASE_GRAPH_VIDEO_URL;
151
        }
152
153
        return $this->enableBetaMode ? static::BASE_GRAPH_URL_BETA : static::BASE_GRAPH_URL;
154
    }
155
156
    /**
157
     * Prepares the request for sending to the client handler.
158
     *
159
     * @param FacebookRequest $request
160
     *
161
     * @return array
162
     */
163
    public function prepareRequestMessage(FacebookRequest $request)
164
    {
165
        $postToVideoUrl = $request->containsVideoUploads();
166
        $url = $this->getBaseGraphUrl($postToVideoUrl) . $request->getUrl();
167
168
        // If we're sending files they should be sent as multipart/form-data
169
        if ($request->containsFileUploads()) {
170
            $requestBody = $request->getMultipartBody();
171
            $request->setHeaders([
172
                'Content-Type' => 'multipart/form-data; boundary=' . $requestBody->getBoundary(),
173
            ]);
174
        } else {
175
            $requestBody = $request->getUrlEncodedBody();
176
            $request->setHeaders([
177
                'Content-Type' => 'application/x-www-form-urlencoded',
178
            ]);
179
        }
180
181
        return [
182
            $url,
183
            $request->getMethod(),
184
            $request->getHeaders(),
185
            $requestBody->getBody(),
186
        ];
187
    }
188
189
    /**
190
     * Makes the request to Graph and returns the result.
191
     *
192
     * @param FacebookRequest $request
193
     *
194
     * @return FacebookResponse
195
     *
196
     * @throws FacebookSDKException
197
     */
198
    public function sendRequest(FacebookRequest $request)
199
    {
200
        if (get_class($request) === 'Facebook\FacebookRequest') {
201
            $request->validateAccessToken();
202
        }
203
204
        list($url, $method, $headers, $body) = $this->prepareRequestMessage($request);
205
206
        // Since file uploads can take a while, we need to give more time for uploads
207
        $timeOut = static::DEFAULT_REQUEST_TIMEOUT;
208
        if ($request->containsFileUploads()) {
209
            $timeOut = static::DEFAULT_FILE_UPLOAD_REQUEST_TIMEOUT;
210
        } elseif ($request->containsVideoUploads()) {
211
            $timeOut = static::DEFAULT_VIDEO_UPLOAD_REQUEST_TIMEOUT;
212
        }
213
214
        // Should throw `FacebookSDKException` exception on HTTP client error.
215
        // Don't catch to allow it to bubble up.
216
        $rawResponse = $this->httpClientHandler->send($url, $method, $body, $headers, $timeOut);
217
218
        static::$requestCount++;
219
220
        $returnResponse = new FacebookResponse(
221
            $request,
222
            $rawResponse->getBody(),
223
            $rawResponse->getHttpResponseCode(),
224
            $rawResponse->getHeaders()
225
        );
226
227
        if ($returnResponse->isError()) {
228
            throw $returnResponse->getThrownException();
229
        }
230
231
        return $returnResponse;
232
    }
233
234
    /**
235
     * Makes a batched request to Graph and returns the result.
236
     *
237
     * @param FacebookBatchRequest $request
238
     *
239
     * @return FacebookBatchResponse
240
     *
241
     * @throws FacebookSDKException
242
     */
243
    public function sendBatchRequest(FacebookBatchRequest $request)
244
    {
245
        $request->prepareRequestsForBatch();
246
        $facebookResponse = $this->sendRequest($request);
247
248
        return new FacebookBatchResponse($request, $facebookResponse);
249
    }
250
}
251