PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 1.10.0
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v1.10.0
2.5.0 2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 All 34 releases
fluent-booking / vendor / wpfluent / framework / src / WPFluent / Http / Client.php

Client.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 1.10.0, at vendor/wpfluent/framework/src/WPFluent/Http/Client.php

459 lines 9.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBooking\Framework\Http;
4
5 use Exception;
6 use BadMethodCallException;
7 use FluentBooking\Framework\Support\Arr;
8 use FluentBooking\Framework\Foundation\App;
9 use FluentBooking\Framework\Http\Request\File;
10
11 /**
12 * @method mixed get(string $url, array $params = []) Send a GET request.
13 * @method mixed post(string $url, array $params = []) Send a POST request.
14 * @method mixed put(string $url, array $params = []) Send a PUT request.
15 * @method mixed patch(string $url, array $params = []) Send a PATCH request.
16 * @method mixed delete(string $url, array $params = []) Send a DELETE request.
17 * @method mixed head(string $url, array $params = []) Send a HEAD request.
18 * @method mixed options(string $url, array $params = []) Send an OPTIONS request.
19 * @method File download(string|File $url) Download a remote file.
20 * @method mixed upload(string $url, string $path, array $fields = [], string $name = 'file') Upload a file to a remote server.
21 */
22
23
24 /**
25 * Some examples:
26 *
27 * // Using an instance:
28 * $client = Client::make('https://example.com');
29 *
30 * $response1 = $client->get('/users');
31 * $response2 = $client->post('/users', ['body' => ['name' => 'Heera']]);
32 * $response3 = $client->put('/users/1', ['body' => ['name' => 'Updated']]);
33 * $response4 = $client->patch('/users/1', [
34 * 'body' => ['email' => 'updated@example.com']]
35 * );
36 * $response5 = $client->delete('/users/1');
37 * $response6 = $client->head('/users');
38 * $response7 = $client->options('/users');
39 *
40 * // Using statically (default base URL is empty):
41 * $response8 = Client::get('https://example.com/users');
42 * $response9 = Client::post('https://example.com/users', [
43 * 'body' => ['name' => 'Static']]
44 * );
45 */
46
47
48 class Client
49 {
50 /**
51 * Base URl for the request.
52 *
53 * @var string
54 */
55 protected $baseUrl = '';
56
57 /**
58 * Cookies to send with the request.
59 *
60 * @var array
61 */
62 protected $cookies = [];
63
64 /**
65 * Headers to send with the request.
66 *
67 * @var array
68 */
69 protected $headers = [];
70
71 /**
72 * Options to set for the request.
73 *
74 * @var array
75 */
76 protected $options = [];
77
78 /**
79 * Request body|Data|params to set in the request.
80 *
81 * @var array
82 */
83 protected $body = [];
84
85 /**
86 * Request query params to pass with the url.
87 *
88 * @var array
89 */
90 protected $query = [];
91
92 /**
93 * Stores args temporarily for then().
94 *
95 * @var null|array
96 */
97 private $args = null;
98
99 /**
100 * Create a new HTTP client.
101 *
102 * @param string $baseUrl
103 * @param array $args
104 */
105 public function __construct($baseUrl = '', $args = [])
106 {
107 $this->baseUrl = rtrim($baseUrl, '/');
108 $this->cookies = $args['cookies'] ?? [];
109 $this->headers = $args['headers'] ?? [];
110 $this->options = $args['options'] ?? [];
111 }
112
113 /**
114 * Create a new HTTP client.
115 *
116 * @param string $baseUrl
117 * @param array $args
118 */
119 public static function make($baseUrl = '', $args = [])
120 {
121 $args['cookies'] = $args['cookies'] ?? [];
122 $args['headers'] = $args['headers'] ?? [];
123 $args['options'] = $args['options'] ?? [];
124 return new static($baseUrl, $args);
125 }
126
127 /**
128 * Sets one or more options.
129 *
130 * @return self
131 */
132 public function withOption($key, $value = null)
133 {
134 $options = is_array($key) ? $key : [$key => $value];
135
136 foreach ($options as $key => $value) {
137 $this->options[$key] = $value;
138 }
139
140 return $this;
141 }
142
143 /**
144 * Sets the blocking option to false (non-blocking).
145 *
146 * @return self
147 */
148 public function async()
149 {
150 return $this->withOption('blocking', false);
151 }
152
153 /**
154 * Sets the sslverify option.
155 *
156 * @return self
157 */
158 public function secure($verify = true)
159 {
160 return $this->withOption('sslverify', $verify);
161 }
162
163 /**
164 * Sets one or more headers.
165 *
166 * @return self
167 */
168 public function withHeader($key, $value = null)
169 {
170 $headers = is_array($key) ? $key : [$key => $value];
171
172 foreach ($headers as $key => $value) {
173 $this->headers[$key] = $value;
174 }
175
176 return $this;
177 }
178
179 /**
180 * Sets one or more cookies.
181 *
182 * @return self
183 */
184 public function withCookie($key, $value = null)
185 {
186 $cookies = is_array($key) ? $key : [$key => $value];
187
188 foreach ($cookies as $key => $value) {
189 $this->cookies[$key] = $value;
190 }
191
192 return $this;
193 }
194
195 /**
196 * Sets one or more request body param.
197 *
198 * @return self
199 */
200 public function withData($key, $value = null)
201 {
202 $data = is_array($key) ? $key : [$key => $value];
203
204 foreach ($data as $key => $value) {
205 $this->body[$key] = $value;
206 }
207
208 return $this;
209 }
210
211 /**
212 * Sets one or more request body param.
213 *
214 * @return self
215 */
216 public function withBody($key, $value = null)
217 {
218 return $this->withData($key, $value);
219 }
220
221 /**
222 * Sets one or more request body param.
223 *
224 * @return self
225 */
226 public function withParam($key, $value = null)
227 {
228 return $this->withData($key, $value);
229 }
230
231 /**
232 * Sets one or more request body param.
233 *
234 * @return self
235 */
236 public function withQuery($key, $value = null)
237 {
238 $data = is_array($key) ? $key : [$key => $value];
239
240 foreach ($data as $key => $value) {
241 $this->query[$key] = $value;
242 }
243
244 return $this;
245 }
246
247 /**
248 * Build the request arguments.
249 *
250 * @param array $params
251 * @param string $method
252 * @return array
253 */
254 protected function buildRequestArgs($params, $method)
255 {
256 $defaultParams = [
257 'body' => [],
258 'cookies' => [],
259 'headers' => [],
260 ];
261
262 $params = wp_parse_args($params[0] ?? [], $defaultParams);
263
264 $options = array_merge($this->options, $params['options'] ?? []);
265
266 $params = [
267 'method' => strtoupper($method),
268 'body' => array_merge($this->body, $params['body']),
269 'cookies' => array_merge($this->cookies, $params['cookies']),
270 'headers' => array_merge($this->headers, $params['headers']),
271 ];
272
273
274 foreach($options as $key => $value) {
275 $params[$key] = $value;
276 }
277
278 return $params;
279 }
280
281 /**
282 * Send the request.
283 *
284 * @param string $url
285 * @param array $args
286 * @return \FluentBooking\Framework\Http\Response
287 */
288 protected function request($url, $args = [])
289 {
290 $parsedUrl = parse_url($url);
291 $delimiter = isset($parsedUrl['query']) ? '&' : '?';
292 $url .= $this->query ? $delimiter . http_build_query($this->query) : '';
293
294 $response = wp_remote_request($url, $args);
295
296 if (is_wp_error($response)) {
297 throw new Exception($response->get_error_message(), 500);
298 }
299
300 $this->cookies = array_merge(
301 $this->cookies,
302 wp_remote_retrieve_cookies($response)
303 );
304
305 return $this->makeResponse($response);
306 }
307
308 /**
309 * Download a remote file.
310 *
311 * @param string $url
312 * @return \FluentBooking\Framework\Http\Request\File
313 * @throws \Exception
314 */
315 public function downloadFile($url)
316 {
317 if (!function_exists('download_url')) {
318 require_once ABSPATH . 'wp-admin/includes/file.php';
319 }
320
321 $parsed = parse_url($url);
322
323 if (!isset($parsed['scheme'])) {
324 $url = trim($this->baseUrl, '/') . '/' . trim($url, '/');
325 }
326
327 if (is_wp_error($file = download_url($url))) {
328 throw new Exception($file->get_error_message(), 500);
329 }
330
331 add_action('shutdown', function () use ($file) {
332 @unlink($file);
333 });
334
335 return new File(
336 $file,
337 basename($url),
338 mime_content_type($file) ?: 'application/octet-stream',
339 filesize($file),
340 UPLOAD_ERR_OK
341 );
342 }
343
344 /**
345 * Upload a file to a remote server.
346 *
347 * @param string $url
348 * @param string $path
349 * @param array $fields
350 * @param string $name
351 * @return \FluentBooking\Framework\Http\Response
352 */
353 public function uploadFile($url, $path, $fields = [], $name = 'file')
354 {
355 $path = $path instanceof File ? $path->getPathname() : $path;
356
357 if (!file_exists($path)) {
358 throw new Exception('File does not exist.', 500);
359 }
360
361 $boundary = wp_generate_password(24, false);
362
363 $headers = [
364 'Accept' => '*/*',
365 'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
366 ];
367
368 $fileName = basename($path);
369 $content = file_get_contents($path);
370 $mime = mime_content_type($path);
371
372 $body = '';
373
374 foreach ($fields as $key => $value) {
375 $body .= "--" . $boundary . "\r\n";
376 $body .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n";
377 $body .= $value . "\r\n";
378 }
379
380 $body .= "--" . $boundary . "\r\n";
381 $body .= 'Content-Disposition: form-data; name="'.$name.'"; filename="' . $fileName . '"' . "\r\n";
382 $body .= 'Content-Type: ' . $mime . "\r\n\r\n";
383 $body .= $content . "\r\n";
384 $body .= "--" . $boundary . "--\r\n";
385
386 $response = wp_remote_post($url, [
387 'headers' => $headers,
388 'body' => $body,
389 'timeout' => 60,
390 ]);
391
392 return $this->makeResponse($response);
393 }
394
395 /**
396 * Build a response object from an anonymous class.
397 *
398 * @param array $response
399 * @return \FluentBooking\Framework\Http\Response
400 */
401 protected function makeResponse($response)
402 {
403 return new Response($response);
404 }
405
406 protected function checkIfValidHttpMethod($method)
407 {
408 $validHttpMethods = [
409 'get', 'post', 'put', 'delete', 'patch', 'options', 'head'
410 ];
411
412 if (!in_array(strtolower($method), $validHttpMethods)) {
413 throw new BadMethodCallException("Method $method does not exist.");
414 }
415 }
416
417 /**
418 * Handles the dynamic calls.
419 *
420 * @param string $method
421 * @param array $args
422 * @return mixed
423 */
424 public function __call($method, $args)
425 {
426 if ($method === 'download') {
427 return $this->downloadFile(...$args);
428 }
429
430 // Handles dynamic method calls like:
431 // get, post and so on.
432 $url = array_shift($args);
433
434 $parsed = parse_url($url);
435
436 if (!isset($parsed['scheme'])) {
437 $url = trim($this->baseUrl, '/') . '/' . trim($url, '/');
438 }
439
440 $this->checkIfValidHttpMethod($method);
441
442 return $this->request(
443 $url, $this->buildRequestArgs($args, $method)
444 );
445 }
446
447 /**
448 * Handle the static dynamic calls.
449 *
450 * @param string $method
451 * @param array $args
452 * @return self
453 */
454 public static function __callStatic($method, $args)
455 {
456 return static::make()->$method(...$args);
457 }
458 }
459