Failed Conditions
Pull Request — master (#1145)
by
unknown
03:10
created

Client::createPSR7RequestFromFacebookRequest()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 13
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 13
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 23
rs 9.8333
ccs 13
cts 13
cp 1
crap 2
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
namespace Facebook;
24
25
use Facebook\Exception\SDKException;
26
use Psr\Http\Client\ClientInterface;
27
use Psr\Http\Message\MessageInterface;
28
use Psr\Http\Message\RequestFactoryInterface;
29
use Psr\Http\Message\RequestInterface;
30
use Psr\Http\Message\StreamFactoryInterface;
31
32
/**
33
 * @package Facebook
34
 */
35
class Client
36
{
37
    /**
38
     * @const string Production Graph API URL.
39
     */
40
    const BASE_GRAPH_URL = 'https://graph.facebook.com';
41
42
    /**
43
     * @const string Graph API URL for video uploads.
44
     */
45
    const BASE_GRAPH_VIDEO_URL = 'https://graph-video.facebook.com';
46
47
    /**
48
     * @const string Beta Graph API URL.
49
     */
50
    const BASE_GRAPH_URL_BETA = 'https://graph.beta.facebook.com';
51
52
    /**
53
     * @const string Beta Graph API URL for video uploads.
54
     */
55
    const BASE_GRAPH_VIDEO_URL_BETA = 'https://graph-video.beta.facebook.com';
56
57
    /**
58
     * @const int The timeout in seconds for a normal request.
59
     */
60
    const DEFAULT_REQUEST_TIMEOUT = 60;
61
62
    /**
63
     * @const int The timeout in seconds for a request that contains file uploads.
64
     */
65
    const DEFAULT_FILE_UPLOAD_REQUEST_TIMEOUT = 3600;
66
67
    /**
68
     * @const int The timeout in seconds for a request that contains video uploads.
69
     */
70
    const DEFAULT_VIDEO_UPLOAD_REQUEST_TIMEOUT = 7200;
71
72
    /**
73
     * @var bool toggle to use Graph beta url
74
     */
75
    protected $enableBetaMode = false;
76
77
    /**
78
     * @var ClientInterface HTTP client handler
79
     */
80
    protected $httpClient;
81
82
    /**
83
     * @var RequestFactoryInterface
84
     */
85
    private $requestFactory;
86
87
    /**
88
     * @var StreamFactoryInterface
89
     */
90
    private $streamFactory;
91
92
    /**
93
     * @var int the number of calls that have been made to Graph
94
     */
95
    public static $requestCount = 0;
96
97
    /**
98
     * Instantiates a new Client object.
99
     *
100
     * @param ClientInterface $httpClient
101
     * @param RequestFactoryInterface $requestFactory
102
     * @param StreamFactoryInterface  $streamFactory
103
     * @param bool            $enableBeta
104
     */
105 41
    public function __construct(
106
        ClientInterface $httpClient,
107
        RequestFactoryInterface $requestFactory,
108
        StreamFactoryInterface $streamFactory,
109
        $enableBeta = false
110
    ) {
111 41
        $this->httpClient = $httpClient;
112 41
        $this->enableBetaMode = $enableBeta;
113 41
        $this->requestFactory = $requestFactory;
114 41
        $this->streamFactory = $streamFactory;
115 41
    }
116
117
    /**
118
     * Sets the HTTP client handler.
119
     *
120
     * @param ClientInterface $httpClient
121
     */
122
    public function setHttpClient(ClientInterface $httpClient)
123
    {
124
        $this->httpClient = $httpClient;
125
    }
126
127
    /**
128
     * Returns the HTTP client handler.
129
     *
130
     * @return ClientInterface
131
     */
132 2
    public function getHttpClient()
133
    {
134 2
        return $this->httpClient;
135
    }
136
137
    /**
138
     * Toggle beta mode.
139
     *
140
     * @param bool $betaMode
141
     */
142 2
    public function enableBetaMode($betaMode = true)
143
    {
144 2
        $this->enableBetaMode = $betaMode;
145 2
    }
146
147
    /**
148
     * Returns the base Graph URL.
149
     *
150
     * @param bool $postToVideoUrl post to the video API if videos are being uploaded
151
     *
152
     * @return string
153
     */
154 15
    public function getBaseGraphUrl($postToVideoUrl = false)
155
    {
156 15
        if ($postToVideoUrl) {
157 2
            return $this->enableBetaMode ? static::BASE_GRAPH_VIDEO_URL_BETA : static::BASE_GRAPH_VIDEO_URL;
158
        }
159
160 13
        return $this->enableBetaMode ? static::BASE_GRAPH_URL_BETA : static::BASE_GRAPH_URL;
161
    }
162
163
    /**
164
     * Prepares the request for sending to the client handler.
165
     * @deprecated
166
     *
167
     * @param Request $request
168
     *
169
     * @return array
170
     */
171 1
    public function prepareRequestMessage(Request $request)
172
    {
173 1
        $postToVideoUrl = $request->containsVideoUploads();
174 1
        $url = $this->getBaseGraphUrl($postToVideoUrl) . $request->getUrl();
175
176
        // If we're sending files they should be sent as multipart/form-data
177 1
        if ($request->containsFileUploads()) {
178 1
            $requestBody = $request->getMultipartBody();
179 1
            $request->setHeaders([
180 1
                'Content-Type' => 'multipart/form-data; boundary=' . $requestBody->getBoundary(),
181
            ]);
182
        } else {
183
            $requestBody = $request->getUrlEncodedBody();
184
            $request->setHeaders([
185
                'Content-Type' => 'application/x-www-form-urlencoded',
186
            ]);
187
        }
188
189
        return [
190 1
            $url,
191 1
            $request->getMethod(),
192 1
            $request->getHeaders(),
193 1
            $requestBody->getBody(),
194
        ];
195
    }
196
197
    /**
198
     * Makes the request to Graph and returns the result.
199
     *
200
     * @param Request $request
201
     *
202
     * @throws SDKException
203
     *
204
     * @return Response
205
     */
206 10
    public function sendRequest(Request $request)
207
    {
208 10
        if (get_class($request) === 'Facebook\Request') {
209 9
            $request->validateAccessToken();
210
        }
211
212 9
        $psr7Request = $this->createPSR7RequestFromFacebookRequest($request);
213
        // Add headers to FacebookRequest
214 9
        $request->setHeaders($this->flattenPSR7Headers($psr7Request, $psr7Request->getHeaders()));
215
216 9
        $psr7Response = $this->httpClient->sendRequest($psr7Request);
217
218 9
        static::$requestCount++;
219
220
        // Prepare headers from associative array to a single string for each header.
221 9
        $responseHeaders = $this->flattenPSR7Headers($psr7Response);
222
223 9
        $Response = new Response(
224 9
            $request,
225 9
            $psr7Response->getBody(),
226 9
            $psr7Response->getStatusCode(),
227 9
            $responseHeaders
228
        );
229
230 9
        if ($Response->isError()) {
231 3
            throw $Response->getThrownException();
232
        }
233
234 7
        return $Response;
235
    }
236
237
    /**
238
     * Makes a batched request to Graph and returns the result.
239
     *
240
     * @param BatchRequest $request
241
     *
242
     * @throws SDKException
243
     *
244
     * @return BatchResponse
245
     */
246 1
    public function sendBatchRequest(BatchRequest $request)
247
    {
248 1
        $request->prepareRequestsForBatch();
249 1
        $Response = $this->sendRequest($request);
250
251 1
        return new BatchResponse($request, $Response);
252
    }
253
254 9
    private function createPSR7RequestFromFacebookRequest(Request $facebookRequest): RequestInterface
255
    {
256 9
        $postToVideoUrl = $facebookRequest->containsVideoUploads();
257 9
        $uri = $this->getBaseGraphUrl($postToVideoUrl) . $facebookRequest->getUrl();
258
259 9
        $psrRequest = $this->requestFactory->createRequest($facebookRequest->getMethod(), $uri);
260
261
        // If we're sending files they should be sent as multipart/form-data
262 9
        if ($facebookRequest->containsFileUploads()) {
263 5
            $requestBody = $facebookRequest->getMultipartBody();
264 5
            $psrRequest = $psrRequest->withHeader(
265 5
                'Content-Type',
266 5
                'multipart/form-data; boundary=' . $requestBody->getBoundary()
267
            );
268
        } else {
269 7
            $requestBody = $facebookRequest->getUrlEncodedBody();
270 7
            $psrRequest = $psrRequest->withHeader('Content-Type', 'application/x-www-form-urlencoded');
271
        }
272
273
        // Create a StreamInterface from request body.
274 9
        $bodyStream = $this->streamFactory->createStream($requestBody->getBody());
275
276 9
        return $psrRequest->withBody($bodyStream);
277
    }
278
279 9
    private function flattenPSR7Headers(MessageInterface $psr7Message, array $initialValues = []): array
280
    {
281 9
        $flattenedHeaders = array_map(
282
            function ($value) { return implode(', ', $value); },
0 ignored issues
show
Coding Style introduced by
Opening brace must be the last content on the line
Loading history...
283 9
            $psr7Message->getHeaders()
284
        );
285
        /* Old Implementation taken from sendRequest()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
286
        foreach ($psr7Message->getHeaders() as $name => $values) {
287
            $initialValues[$name] = implode(", ", $values);
288
        }*/
289 9
        return array_merge($initialValues, $flattenedHeaders);
290
    }
291
}
292