PluginProbe ʕ •ᴥ•ʔ
Meta for WooCommerce / 1.11.3
Meta for WooCommerce v1.11.3
3.7.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.11.1 1.11.2 1.11.3 1.11.4 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 2.0.0 2.0.1 2.0.2 2.0.3 2.0.4 2.0.5 2.1.0 2.1.1 2.1.2 2.1.3 2.1.4 2.2.0 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5 2.4.0 2.4.1 2.5.0 2.5.1 2.6.0 2.6.1 2.6.10 2.6.11 2.6.12 2.6.13 2.6.14 2.6.15 2.6.16 2.6.17 2.6.18 2.6.19 2.6.2 2.6.20 2.6.21 2.6.22 2.6.23 2.6.24 2.6.25 2.6.26 2.6.27 2.6.28 2.6.29 2.6.3 2.6.30 2.6.4 2.6.5 2.6.6 2.6.7 2.6.8 2.6.9 3.0.0 3.0.1 3.0.10 3.0.11 3.0.12 3.0.13 3.0.14 3.0.15 3.0.16 3.0.17 3.0.18 3.0.19 3.0.2 3.0.20 3.0.21 3.0.22 3.0.23 3.0.24 3.0.25 3.0.26 3.0.27 3.0.28 3.0.29 3.0.3 3.0.30 3.0.31 3.0.32 3.0.33 3.0.34 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.10 3.1.11 3.1.12 3.1.13 3.1.14 3.1.15 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 3.2.0 3.2.1 3.2.10 3.2.2 3.2.3 3.2.4 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.4.0 3.4.1 3.4.10 3.4.2 3.4.3 3.4.4 3.4.5 3.4.6 3.4.7 3.4.8 3.4.9 3.5.10 3.5.11 3.5.12 3.5.13 3.5.14 3.5.15 3.5.16 3.5.17 3.5.18 3.5.2 3.5.3 3.5.4 3.5.5 3.5.6 3.5.7 3.5.8 3.5.9 3.6.0 3.6.1 3.6.2 3.6.3 3.7.0
facebook-for-woocommerce / includes / fbgraph.php
facebook-for-woocommerce / includes Last commit date
Integrations 6 years ago Products 6 years ago Utilities 6 years ago test 6 years ago AJAX.php 6 years ago Admin.php 6 years ago Lifecycle.php 6 years ago Products.php 6 years ago fbasync.php 6 years ago fbbackground.php 6 years ago fbgraph.php 6 years ago fbinfobanner.php 6 years ago fbproduct.php 6 years ago fbproductfeed.php 6 years ago fbutils.php 6 years ago fbwpml.php 6 years ago
fbgraph.php
542 lines
1 <?php
2 /**
3 * Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
4 *
5 * This source code is licensed under the license found in the
6 * LICENSE file in the root directory of this source tree.
7 *
8 * @package FacebookCommerce
9 */
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
16
17 if ( ! class_exists( 'WC_Facebookcommerce_Graph_API' ) ) :
18
19 if ( ! class_exists( 'WC_Facebookcommerce_Async_Request' ) ) {
20 include_once 'fbasync.php';
21 }
22
23 /**
24 * FB Graph API helper functions
25 */
26 class WC_Facebookcommerce_Graph_API {
27 const GRAPH_API_URL = 'https://graph.facebook.com/v2.9/';
28 const CURL_TIMEOUT = 500;
29
30 /**
31 * Cache the api_key
32 */
33 var $api_key;
34
35 /**
36 * Init
37 */
38 public function __construct( $api_key ) {
39 $this->api_key = $api_key;
40 }
41
42
43 /**
44 * Issues a GET request to the Graph API.
45 *
46 * @param string $url request URL
47 * @param string $api_key Graph API key
48 * @return array|\WP_Error
49 */
50 public function _get( $url, $api_key = '' ) {
51
52 $api_key = $api_key ?: $this->api_key;
53
54 $request_args = [
55 'headers' => [
56 'Authorization' => 'Bearer ' . $api_key,
57 ],
58 'timeout' => self::CURL_TIMEOUT,
59 ];
60
61 $response = wp_remote_get( $url, $request_args );
62
63 $this->log_request( $url, $request_args, $response );
64
65 return $response;
66 }
67
68
69 /**
70 * Performs a Graph API request to the given URL.
71 *
72 * Throws an exception if a WP_Error is returned or we receive a 401 Not Authorized response status.
73 *
74 * @since 1.10.2
75 *
76 * @param string $url
77 * @throws Framework\SV_WC_API_Exception
78 * @return array
79 */
80 public function perform_request( $url ) {
81
82 $request_args = [
83 'headers' => [
84 'Authorization' => 'Bearer ' . $this->api_key,
85 ],
86 'timeout' => self::CURL_TIMEOUT,
87 ];
88
89 $response = wp_remote_get( $url, $request_args );
90
91 $this->log_request( $url, $request_args, $response );
92
93 if ( is_wp_error( $response ) ) {
94
95 throw new Framework\SV_WC_API_Exception( $response->get_error_message(), $response->get_error_code() );
96
97 } elseif ( 401 === (int) wp_remote_retrieve_response_code( $response ) ) {
98
99 $response_body = json_decode( wp_remote_retrieve_body( $response ) );
100
101 if ( isset( $response_body->error->code, $response_body->error->message ) ) {
102 throw new Framework\SV_WC_API_Exception( $response_body->error->message, $response_body->error->code );
103 } else {
104 throw new Framework\SV_WC_API_Exception( sprintf( __( 'HTTP %s: %s', 'facebook-for-woocommerce' ), wp_remote_retrieve_response_code( $response ), wp_remote_retrieve_response_message( $response ) ) );
105 }
106 }
107
108 return $response;
109 }
110
111
112 public function _post( $url, $data, $api_key = '' ) {
113 if ( class_exists( 'WC_Facebookcommerce_Async_Request' ) ) {
114 return self::_post_async( $url, $data );
115 } else {
116 return self::_post_sync( $url, $data );
117 }
118 }
119
120 public function _post_sync( $url, $data, $api_key = '' ) {
121 $api_key = $api_key ?: $this->api_key;
122
123 $request_args = [
124 'body' => $data,
125 'headers' => [
126 'Authorization' => 'Bearer ' . $api_key,
127 ],
128 'timeout' => self::CURL_TIMEOUT,
129 ];
130
131 $response = wp_remote_post( $url, $request_args );
132
133 $this->log_request( $url, $request_args, $response, 'POST' );
134
135 return $response;
136 }
137
138
139 /**
140 * Issues an asynchronous POST request to the Graph API.
141 *
142 * @param string $url request URL
143 * @param array $data request data
144 * @param string $api_key Graph API key
145 * @return array|\WP_Error
146 */
147 public function _post_async( $url, $data, $api_key = '' ) {
148
149 if ( ! class_exists( 'WC_Facebookcommerce_Async_Request' ) ) {
150 return;
151 }
152
153 $api_key = $api_key ?: $this->api_key;
154
155 $request_args = [
156 'body' => $data,
157 'headers' => [
158 'Authorization' => 'Bearer ' . $api_key,
159 ],
160 'timeout' => self::CURL_TIMEOUT,
161 ];
162
163 $fbasync = new WC_Facebookcommerce_Async_Request();
164
165 $fbasync->query_url = $url;
166 $fbasync->query_args = array();
167 $fbasync->post_args = $request_args;
168
169 $response = $fbasync->dispatch();
170
171 $this->log_request( $url, $request_args, $response, 'POST' );
172
173 return $response;
174 }
175
176
177 /**
178 * Issues a DELETE request to the Graph API.
179 *
180 * @param string $url request URL
181 * @param string $api_key Graph API key
182 * @return array|\WP_Error
183 */
184 public function _delete( $url, $api_key = '' ) {
185
186 $api_key = $api_key ?: $this->api_key;
187
188 $request_args = [
189 'headers' => [
190 'Authorization' => 'Bearer ' . $api_key,
191 ],
192 'timeout' => self::CURL_TIMEOUT,
193 'method' => 'DELETE',
194 ];
195
196 $response = wp_remote_request( $url, $request_args );
197
198 $this->log_request( $url, $request_args, $response, 'DELETE' );
199
200 return $response;
201 }
202
203
204 /**
205 * Logs the request and response data.
206 *
207 * @since 1.10.2
208 *
209 * @param $url
210 * @param $request_args
211 * @param array|\WP_Error $response WordPress response object
212 * @param string $method
213 */
214 private function log_request( $url, $request_args, $response, $method = '' ) {
215
216 // bail if this class is loaded incorrectly or logging is disabled
217 if ( ! function_exists( 'facebook_for_woocommerce' ) || ! facebook_for_woocommerce()->get_integration()->is_debug_mode_enabled() ) {
218 return;
219 }
220
221 // add the URI to the data
222 $request_data = array_merge( [
223 'uri' => $url,
224 ], $request_args );
225
226 // the request args may not include the method, so allow it to be set
227 if ( $method ) {
228 $request_data['method'] = $method;
229 }
230
231 // mask the page access token
232 if ( ! empty( $request_data['headers']['Authorization'] ) ) {
233
234 $auth_value = $request_data['headers']['Authorization'];
235
236 $request_data['headers']['Authorization'] = str_replace( $auth_value, str_repeat( '*', strlen( $auth_value ) ), $auth_value );
237 }
238
239 // if there was a problem
240 if ( is_wp_error( $response ) ) {
241
242 $code = $response->get_error_code();
243 $message = $response->get_error_message();
244 $headers = [];
245 $body = '';
246
247 } else {
248
249 $headers = wp_remote_retrieve_headers( $response );
250
251 if ( is_object( $headers ) ) {
252 $headers = $headers->getAll();
253 } elseif ( ! is_array( $headers ) ) {
254 $headers = [];
255 }
256
257 $code = wp_remote_retrieve_response_code( $response );
258 $message = wp_remote_retrieve_response_message( $response );
259 $body = wp_remote_retrieve_body( $response );
260 }
261
262 $response_data = [
263 'code' => $code,
264 'message' => $message,
265 'headers' => $headers,
266 'body' => $body,
267 ];
268
269 facebook_for_woocommerce()->log_api_request( $request_data, $response_data );
270 }
271
272
273 // GET https://graph.facebook.com/vX.X/{page-id}/?fields=name
274 public function get_page_name( $page_id, $api_key = '' ) {
275 $api_key = $api_key ?: $this->api_key;
276 $url = $this->build_url( $page_id, '/?fields=name' );
277 $response = self::_get( $url, $api_key );
278
279 if ( is_wp_error( $response ) ) {
280 WC_Facebookcommerce_Utils::log( $response->get_error_message() );
281 return '';
282 }
283
284 if ( $response['response']['code'] != '200' ) {
285 return '';
286 }
287
288 $response_body = json_decode( wp_remote_retrieve_body( $response ) );
289
290 return isset( $response_body->name ) ? $response_body->name : '';
291 }
292
293
294 /**
295 * Gets a Facebook Page URL.
296 *
297 * Endpoint: https://graph.facebook.com/vX.X/{page-id}/?fields=link
298 *
299 * @param string|int $page_id page identifier
300 * @param string $api_key API key
301 * @return string URL
302 */
303 public function get_page_url( $page_id, $api_key = '' ) {
304
305 $api_key = $api_key ?: $this->api_key;
306 $request = $this->build_url( $page_id, '/?fields=link' );
307 $response = $this->_get( $request, $api_key );
308 $page_url = '';
309
310 if ( is_wp_error( $response ) ) {
311
312 \WC_Facebookcommerce_Utils::log( $response->get_error_message() );
313
314 } elseif ( 200 === (int) $response['response']['code'] ) {
315
316 $response_body = wp_remote_retrieve_body( $response );
317 $page_url = json_decode( $response_body )->link;
318 }
319
320 return $page_url;
321 }
322
323
324 /**
325 * Determines whether the product catalog ID is valid.
326 *
327 * Returns true if the product catalog ID can be successfully retrieved using the Graph API.
328 *
329 * TODO: deprecate this methid in 1.11.0 or newer {WV 2020-03-12}
330 *
331 * @param int $product_catalog_id the ID of the product catalog
332 * @return bool
333 */
334 public function validate_product_catalog( $product_catalog_id ) {
335
336 try {
337 $is_valid = $this->is_product_catalog_valid( $product_catalog_id );
338 } catch ( Framework\SV_WC_API_Exception $e ) {
339 $is_valid = false;
340 }
341
342 return $is_valid;
343 }
344
345
346 /**
347 * Determines whether the product catalog ID is valid.
348 *
349 * Returns true if the product catalog ID can be successfully retrieved using the Graph API.
350 *
351 * @since 1.10.2
352 *
353 * @param int $product_catalog_id the ID of the product catalog
354 * @return boolean
355 * @throws Framework\SV_WC_API_Exception
356 */
357 public function is_product_catalog_valid( $product_catalog_id ) {
358
359 $response = $this->perform_request( $this->build_url( $product_catalog_id ) );
360
361 return 200 === (int) wp_remote_retrieve_response_code( $response );
362 }
363
364
365 // POST https://graph.facebook.com/vX.X/{product-catalog-id}/product_groups
366 public function create_product_group( $product_catalog_id, $data ) {
367 $url = $this->build_url( $product_catalog_id, '/product_groups' );
368 return self::_post( $url, $data );
369 }
370
371 // POST https://graph.facebook.com/vX.X/{product-group-id}/products
372 public function create_product_item( $product_group_id, $data ) {
373 $url = $this->build_url( $product_group_id, '/products' );
374 return self::_post( $url, $data );
375 }
376
377 public function update_product_group( $product_catalog_id, $data ) {
378 $url = $this->build_url( $product_catalog_id );
379 return self::_post( $url, $data );
380 }
381
382 public function update_product_item( $product_id, $data ) {
383 $url = $this->build_url( $product_id );
384 return self::_post( $url, $data );
385 }
386
387 public function delete_product_item( $product_item_id ) {
388 $product_item_url = $this->build_url( $product_item_id );
389 return self::_delete( $product_item_url );
390 }
391
392 public function delete_product_group( $product_group_id ) {
393 $product_group_url = $this->build_url( $product_group_id );
394 return self::_delete( $product_group_url );
395 }
396
397 public function log( $ems_id, $message, $error ) {
398 $log_url = $this->build_url( $ems_id, '/log_events' );
399
400 $data = array(
401 'message' => $message,
402 'error' => $error,
403 );
404
405 self::_post( $log_url, $data );
406 }
407
408 public function log_tip_event( $tip_id, $channel_id, $event ) {
409 $tip_event_log_url = $this->build_url( '', '/log_tip_events' );
410
411 $data = array(
412 'tip_id' => $tip_id,
413 'channel_id' => $channel_id,
414 'event' => $event,
415 );
416
417 self::_post( $tip_event_log_url, $data );
418 }
419
420 public function create_upload( $facebook_feed_id, $path_to_feed_file ) {
421 $url = $this->build_url(
422 $facebook_feed_id,
423 '/uploads?access_token=' . $this->api_key
424 );
425
426 $data = [
427 'file' => new CurlFile( $path_to_feed_file, 'text/csv' ),
428 'update_only' => true,
429 ];
430
431 $curl = curl_init();
432 curl_setopt_array(
433 $curl,
434 array(
435 CURLOPT_URL => $url,
436 CURLOPT_POST => 1,
437 CURLOPT_POSTFIELDS => $data,
438 CURLOPT_RETURNTRANSFER => 1,
439 )
440 );
441 $response = curl_exec( $curl );
442 if ( curl_errno( $curl ) ) {
443 WC_Facebookcommerce_Utils::fblog( $response );
444 return null;
445 }
446 return WC_Facebookcommerce_Utils::decode_json( $response, true );
447 }
448
449 public function create_feed( $facebook_catalog_id, $data ) {
450 $url = $this->build_url( $facebook_catalog_id, '/product_feeds' );
451 // success API call will return {id: <product feed id>}
452 // failure API will return {error: <error message>}
453 return self::_post( $url, $data );
454 }
455
456 public function get_upload_status( $facebook_upload_id ) {
457 $url = $this->build_url( $facebook_upload_id, '/?fields=end_time' );
458 // success API call will return
459 // {id: <upload id>, end_time: <time when upload completes>}
460 // failure API will return {error: <error message>}
461 return self::_get( $url );
462 }
463
464 // success API call will return a JSON of tip info
465 public function get_tip_info( $external_merchant_settings_id ) {
466 $url = $this->build_url( $external_merchant_settings_id, '/?fields=connect_woo' );
467 $response = self::_get( $url, $this->api_key );
468 $data = array(
469 'response' => $response,
470 );
471 if ( is_wp_error( $response ) ) {
472 $data['error_type'] = 'is_wp_error';
473 WC_Facebookcommerce_Utils::fblog(
474 'Failed to get AYMT tip info via API.',
475 $data,
476 true
477 );
478 return;
479 }
480 if ( $response['response']['code'] != '200' ) {
481 $data['error_type'] = 'Non-200 error code from FB';
482 WC_Facebookcommerce_Utils::fblog(
483 'Failed to get AYMT tip info via API.',
484 $data,
485 true
486 );
487 return;
488 }
489
490 $response_body = wp_remote_retrieve_body( $response );
491 $connect_woo =
492 WC_Facebookcommerce_Utils::decode_json( $response_body )->connect_woo;
493 if ( ! isset( $connect_woo ) ) {
494 $data['error_type'] = 'Response body not set';
495 WC_Facebookcommerce_Utils::fblog(
496 'Failed to get AYMT tip info via API.',
497 $data,
498 true
499 );
500 }
501 return $connect_woo;
502 }
503
504 public function get_facebook_id( $facebook_catalog_id, $product_id ) {
505 $param = 'catalog:' . (string) $facebook_catalog_id . ':' .
506 base64_encode( $product_id ) . '/?fields=id,product_group{id}';
507 $url = $this->build_url( '', $param );
508 // success API call will return
509 // {id: <fb product id>, product_group{id} <fb product group id>}
510 // failure API will return {error: <error message>}
511 return self::_get( $url );
512 }
513
514 public function check_product_info( $facebook_catalog_id, $product_id, $pr_v ) {
515 $param = 'catalog:' . (string) $facebook_catalog_id . ':' .
516 base64_encode( $product_id ) . '/?fields=id,name,description,price,' .
517 'sale_price,sale_price_start_date,sale_price_end_date,image_url,' .
518 'visibility';
519 if ( $pr_v ) {
520 $param = $param . ',additional_variant_attributes{value}';
521 }
522 $url = $this->build_url( '', $param );
523 // success API call will return
524 // {id: <fb product id>, name,description,price,sale_price,sale_price_start_date
525 // sale_price_end_date
526 // failure API will return {error: <error message>}
527 return self::_get( $url );
528 }
529
530 public function set_default_variant( $product_group_id, $data ) {
531 $url = $this->build_url( $product_group_id );
532 return self::_post( $url, $data );
533 }
534
535 private function build_url( $field_id, $param = '' ) {
536 return self::GRAPH_API_URL . (string) $field_id . $param;
537 }
538
539 }
540
541 endif;
542