File "facebook-integration-test.php"
Full Path: /home/warrior1/public_html/languages/wp-content/plugins/facebook-for-woocommerce/includes/test/facebook-integration-test.php
File size: 16.65 KB
MIME-type: text/x-php
Charset: utf-8
<?php
// phpcs:ignoreFile
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
*
* @package FacebookCommerce
*
* usage:
* 1. set WP_DEBUG = true and WP_DEBUG_DISPLAY = false
* 2. append "&fb_test_product_sync=true" to the url when you are on facebook-for-woocommerce setting pages
* 3. refresh the page to launch test
* https://codex.wordpress.org/WP_DEBUG
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
require_once dirname( __DIR__ ) . '/fbutils.php';
require_once 'fbproductfeed-test.php';
if ( ! class_exists( 'WC_Facebook_Integration_Test' ) ) :
/**
* This tests the upload of test objects into Facebook using the plugin's
* infrastructure and checks to see if the product field have been correctly
* uploaded into FB.
*/
class WC_Facebook_Integration_Test {
const FB_PRODUCT_GROUP_ID = 'fb_product_group_id';
const FB_PRODUCT_ITEM_ID = 'fb_product_item_id';
const MAX_SLEEP_IN_SEC = 90;
const MAX_TIME = 'T23:59+00:00';
const MIN_TIME = 'T00:00+00:00';
/** Class Instance */
private static $instance;
/** @var WC_Facebookcommerce_Integration full integration object */
public static $commerce = null;
/** @var WC_Facebookcommerce_Graph_API */
public static $fbgraph = null;
public static $test_mode = false;
// simple products' id and variable products' parent_id
public static $wp_post_ids = array();
// FB product item retailer id.
public static $retailer_ids = array();
// product and product_variation post id for test
public $product_post_wpid = null;
public static $test_pass = 1;
/**
* Get the class instance
*/
public static function get_instance( $commerce ) {
return null === self::$instance
? ( self::$instance = new self( $commerce ) )
: self::$instance;
}
/**
* Constructor
*/
public function __construct( $commerce ) {
self::$commerce = $commerce;
}
function check_product_create() {
if ( count( self::$retailer_ids ) < 3 ) {
WC_Facebookcommerce_Utils::log( 'Test - Failed to create 3 product items.' );
WC_Facebookcommerce_Utils::set_test_fail_reason(
'Failed to create 3 product items.',
( new Exception() )->getTraceAsString()
);
return false;
}
if ( count( self::$retailer_ids ) > 3 ) {
WC_Facebookcommerce_Utils::log(
'Test - Failed to skip invisible products.'
);
WC_Facebookcommerce_Utils::set_test_fail_reason(
'Failed to skip invisible products.',
( new Exception() )->getTraceAsString()
);
return false;
}
// Check 3 products have been created.
for ( $i = 0; $i < 3; $i++ ) {
$product_type = $i == 0 ? 'Simple' : 'Variable';
$retailer_id = self::$retailer_ids[ $i ];
$item_fbid =
$this->check_fbid_api( self::FB_PRODUCT_ITEM_ID, $retailer_id );
$group_fbid =
$this->check_fbid_api( self::FB_PRODUCT_GROUP_ID, $retailer_id );
if ( ! $item_fbid || ! $group_fbid ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $product_type .
' product failed to create.'
);
WC_Facebookcommerce_Utils::set_test_fail_reason(
$product_type .
' product failed to create.',
( new Exception() )->getTraceAsString()
);
return false;
}
}
// Check product detailed as expected.
$data = array(
'name' => 'a simple product for test',
'price' => '20.00',
'description' => 'This is to test a simple product.',
'sale_price' => '10.00',
'sale_price_dates_from' =>
date_i18n( 'Y-m-d', strtotime( 'now' ) ) . self::MIN_TIME,
'sale_price_dates_to' =>
date_i18n( 'Y-m-d', strtotime( '+10 day' ) ) . self::MAX_TIME,
'visibility' => 'published',
);
$simple_product_result =
$this->check_product_info( self::$retailer_ids[0], false, $data );
if ( ! $simple_product_result ) {
WC_Facebookcommerce_Utils::log(
'Test - Simple product failed to match ' .
'product details.'
);
WC_Facebookcommerce_Utils::set_test_fail_reason(
'Simple product failed to'
. ' match product details.',
( new Exception() )->getTraceAsString()
);
return false;
}
$data = array(
'name' => 'a variable product for test',
'price' => '30.00',
'description' => 'This is to test a variable product. - Red',
'additional_variant_attributes' => array( 'value' => 'Red' ),
'visibility' => 'published',
);
$variable_product_result =
$this->check_product_info( self::$retailer_ids[1], true, $data );
if ( ! $variable_product_result ) {
WC_Facebookcommerce_Utils::log(
'Test - Variable product failed to match product details.'
);
WC_Facebookcommerce_Utils::set_test_fail_reason(
'Variable product failed to match product details.',
( new Exception() )->getTraceAsString()
);
return false;
}
return true;
}
function check_fbid_api( $fbid_type, $fb_retailer_id ) {
$product_fbid_result = self::$fbgraph->get_facebook_id(
self::$commerce->get_product_catalog_id(),
$fb_retailer_id,
true
);
if ( is_wp_error( $product_fbid_result ) ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $product_fbid_result->get_error_message()
);
WC_Facebookcommerce_Utils::set_test_fail_reason(
'There was an issue connecting to the Facebook API: ' .
$product_fbid_result->get_error_message(),
( new Exception() )->getTraceAsString()
);
return false;
}
if ( $product_fbid_result && isset( $product_fbid_result['body'] ) ) {
$body = WC_Facebookcommerce_Utils::decode_json(
$product_fbid_result['body'],
true
);
if ( $body && isset( $body['id'] ) ) {
if ( $fbid_type == self::FB_PRODUCT_GROUP_ID ) {
$fb_id =
isset( $body['product_group'] )
? $body['product_group']['id']
: false;
} else {
$fb_id = $body['id'];
}
return $fb_id;
}
}
return false;
}
function check_product_info( $retailer_id, $has_variant, $data ) {
$prod_info_result = self::$fbgraph->check_product_info(
self::$commerce->get_product_catalog_id(),
$retailer_id,
$has_variant
);
if ( is_wp_error( $prod_info_result ) ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $prod_info_result->get_error_message()
);
WC_Facebookcommerce_Utils::set_test_fail_reason(
'There was an issue connecting to the Facebook API: ' .
$prod_info_result->get_error_message(),
( new Exception() )->getTraceAsString()
);
return false;
}
$match = true;
if ( $prod_info_result && isset( $prod_info_result['body'] ) ) {
$body = WC_Facebookcommerce_Utils::decode_json(
$prod_info_result['body'],
true
);
if ( ! $body ) {
return false;
}
if ( $body['name'] != $data['name'] ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $retailer_id . " doesn\'t match name."
);
$match = false;
}
if ( $body['description'] != $data['description'] ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $retailer_id . " doesn\'t match description."
);
$match = false;
}
// Woo doesn't have API to return currency symbol.
// FB graph API only support to response with a currency symbol price.
// No php built-in function to support cast html number to symbol.
// Compare numeric price only.
$price = floatval( preg_replace( '/[^\d\.]+/', '', $body['price'] ) );
if ( $price != $data['price'] ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $retailer_id . " doesn\'t match price."
);
$match = false;
}
// Check sale price and dates.
if ( isset( $data['sale_price'] ) ) {
$sale_price = floatval(
preg_replace( '/[^\d\.]+/', '', $body['sale_price'] )
);
if ( $sale_price != $data['sale_price'] ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $retailer_id . " doesn\'t match sale price."
);
$match = false;
}
if ( $body['sale_price_start_date'] != $data['sale_price_dates_from'] ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $retailer_id . " doesn\'t match sale price start date"
);
$match = false;
}
if ( $body['sale_price_end_date'] != $data['sale_price_dates_to'] ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $retailer_id . " doesn\'t match sale price end date."
);
$match = false;
}
}
if ( $body['visibility'] != $data['visibility'] ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $retailer_id . " doesn\'t match visibility."
);
$match = false;
}
if ( $has_variant &&
( ! isset( $body['additional_variant_attributes'] ) ||
$body['additional_variant_attributes'][0]['value'] !=
$data['additional_variant_attributes']['value'] ) ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $retailer_id . " doesn\'t match variation."
);
$match = false;
}
}
return $match;
}
// Don't early return to prevent haunting product id.
function clean_up() {
$failure = false;
foreach ( self::$wp_post_ids as $post_id ) {
$delete_post_result = wp_delete_post( $post_id );
// return false or null if failed.
if ( ! $delete_post_result ) {
WC_Facebookcommerce_Utils::log( 'Test - Fail to delete post ' . $post_id );
WC_Facebookcommerce_Utils::set_test_fail_reason(
'Fail to delete post ' . $post_id,
( new Exception() )->getTraceAsString()
);
$failure = true;
}
}
self::$wp_post_ids = array();
$this->sleep_til_upload_complete( 60 );
foreach ( self::$retailer_ids as $retailer_id ) {
$item_fbid =
$this->check_fbid_api( self::FB_PRODUCT_ITEM_ID, $retailer_id );
$group_fbid =
$this->check_fbid_api( self::FB_PRODUCT_GROUP_ID, $retailer_id );
if ( $item_fbid || $group_fbid ) {
WC_Facebookcommerce_Utils::log(
'Test - Failed to delete product ' .
$retailer_id . ' via plugin deletion hook.'
);
WC_Facebookcommerce_Utils::set_test_fail_reason(
'Failed to delete product ' . $retailer_id .
' via plugin deletion hook.',
( new Exception() )->getTraceAsString()
);
$failure = true;
}
}
self::$retailer_ids = array();
return ! $failure;
}
function create_data() {
$prod_and_variant_wpid = array();
// Gets term object from Accessories in the database.
$term = get_term_by( 'name', 'Accessories', 'product_cat' );
// Accessories should be a default category.
// If not exist, set categories term first.
if ( ! $term ) {
$term = wp_insert_term(
'Accessories', // the term
'product_cat', // the taxonomy
array(
'slug' => 'accessories',
)
);
}
$data = array(
'post_content' => 'This is to test a simple product.',
'post_title' => 'a simple product for test',
'post_status' => 'publish',
'post_type' => 'product',
'term' => $term,
'price' => 20,
'sale_price' => 10,
'sale_price_dates_from' => strtotime( 'now' ),
'sale_price_dates_to' => strtotime( '+10 day' ),
);
$simple_product_result =
$this->create_test_simple_product( $data, $prod_and_variant_wpid );
if ( ! $simple_product_result ) {
return false;
}
// Test an invisible product - invisible products won't be synced by feed.
$data['visibility'] = false;
$simple_product_result =
$this->create_test_simple_product( $data, $prod_and_variant_wpid );
if ( ! $simple_product_result ) {
return false;
}
$data['post_content'] = 'This is to test a variable product.';
$data['post_title'] = 'a variable product for test';
$data['price'] = 30;
// Test variable products.
$variable_product_result =
$this->create_test_variable_product( $data, $prod_and_variant_wpid );
if ( ! $variable_product_result ) {
return false;
}
return $prod_and_variant_wpid;
}
function create_test_simple_product( $data, &$prod_and_variant_wpid ) {
$post_id = $this->fb_insert_post( $data, 'Simple' );
if ( ! $post_id ) {
return false;
}
array_push( $prod_and_variant_wpid, $post_id );
update_post_meta( $post_id, '_regular_price', $data['price'] );
update_post_meta( $post_id, '_sale_price', $data['sale_price'] );
update_post_meta( $post_id, '_sale_price_dates_from', $data['sale_price_dates_from'] );
update_post_meta( $post_id, '_sale_price_dates_to', $data['sale_price_dates_to'] );
wp_set_object_terms( $post_id, 'simple', 'product_type' );
// Invisible products won't be synced by feed.
if ( isset( $data['visibility'] ) ) {
$terms = array( 'exclude-from-catalog', 'exclude-from-search' );
wp_set_object_terms( $post_id, $terms, 'product_visibility' );
} else {
array_push( self::$wp_post_ids, $post_id );
array_push( self::$retailer_ids, 'wc_post_id_' . $post_id );
}
$product = wc_get_product( $post_id );
$product->set_stock_status( 'instock' );
wp_set_object_terms( $post_id, $data['term']->term_id, 'product_cat' );
return true;
}
function create_test_variable_product( $data, &$prod_and_variant_wpid ) {
$post_id = $this->fb_insert_post( $data, 'Variable' );
if ( ! $post_id ) {
return false;
}
wp_set_object_terms( $post_id, 'variable', 'product_type' );
array_push( $prod_and_variant_wpid, $post_id );
array_push( self::$wp_post_ids, $post_id );
// Gets term object from Accessories in the database.
$term = get_term_by( 'name', 'Accessories', 'product_cat' );
wp_set_object_terms( $post_id, $term->term_id, 'product_cat' );
// Set up attributes.
$avail_attribute_values = array(
'Red',
'Blue',
);
wp_set_object_terms( $post_id, $avail_attribute_values, 'pa_color' );
$thedata = array(
'pa_color' => array(
'name' => 'pa_color',
'value' => '',
'is_visible' => '1',
'is_variation' => '1',
'is_taxonomy' => '1',
),
);
update_post_meta( $post_id, '_product_attributes', $thedata );
// Insert variations.
$variation_data = array(
'post_content' => 'This is to test a variable product. - Red',
'post_status' => 'publish',
'post_type' => 'product_variation',
'post_parent' => $post_id,
'price' => 30,
);
$variation_red = $this->fb_insert_post( $variation_data, 'Variation' );
if ( ! $variation_red ) {
return;
}
$this->fb_update_variation_meta(
$prod_and_variant_wpid,
$variation_red,
'Red',
$variation_data
);
$variation_data['post_content'] = 'a variable product for test - Blue';
$variation_blue = $this->fb_insert_post( $variation_data, 'Variatoin' );
if ( ! $variation_blue ) {
return false;
}
$this->fb_update_variation_meta(
$prod_and_variant_wpid,
$variation_blue,
'Blue',
$variation_data
);
$product = wc_get_product( $variation_blue );
$product->set_stock_status( 'instock' );
wp_set_object_terms( $variation_blue, 'variation', 'product_type' );
return true;
}
function fb_update_variation_meta(
&$prod_and_variant_wpid,
$variation_id,
$value,
$data ) {
array_push( $prod_and_variant_wpid, $variation_id );
array_push( self::$retailer_ids, 'wc_post_id_' . $variation_id );
$attribute_term = get_term_by( 'name', $value, 'pa_color' );
update_post_meta( $variation_id, 'attribute_pa_color', $attribute_term->slug );
update_post_meta( $variation_id, '_price', $data['price'] );
update_post_meta( $variation_id, '_regular_price', $data['price'] );
wp_set_object_terms( $variation_id, 'variation', 'product_type' );
$product = wc_get_product( $variation_id );
$product->set_stock_status( 'instock' );
}
function fb_insert_post( $data, $p_type ) {
$postarr = array_intersect_key(
$data,
array_flip(
array(
'post_content',
'post_title',
'post_status',
'post_type',
'post_parent',
)
)
);
$post_id = wp_insert_post( $postarr );
if ( is_wp_error( $post_id ) ) {
WC_Facebookcommerce_Utils::log(
'Test - ' . $p_type .
' product wp_insert_post' . 'failed: ' . json_encode( $post_id )
);
return false;
} else {
return $post_id;
}
}
/**
* IMPORTANT! Wait for Ents creation and prevent race condition.
**/
function sleep_til_upload_complete( $sec ) {
sleep( $sec );
}
function set_product_wpid( $product_post_wpid ) {
WC_Facebook_Product_Feed_Test_Mock::$product_post_wpid = $product_post_wpid;
}
}
endif;