Version Description
Download this release
Release Info
Developer | SkyVerge |
Plugin | Facebook for WooCommerce |
Version | 2.0.2 |
Comparing to | |
See all releases |
Code changes from version 2.0.1 to 2.0.2
- changelog.txt +7 -0
- class-wc-facebookcommerce.php +1 -1
- facebook-commerce.php +35 -36
- facebook-for-woocommerce.php +2 -2
- i18n/languages/facebook-for-woocommerce.pot +25 -25
- includes/Handlers/Connection.php +25 -7
- includes/Integrations/Bookings.php +88 -0
- includes/Integrations/Integrations.php +1 -0
- includes/Products.php +95 -4
- includes/Products/Sync.php +2 -20
- includes/Products/Sync/Background.php +36 -26
- includes/fbproduct.php +27 -63
- includes/fbproductfeed.php +9 -6
- readme.txt +8 -1
changelog.txt
CHANGED
@@ -1,5 +1,12 @@
|
|
1 |
*** Facebook for WooCommerce Changelog ***
|
2 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3 |
2020.08.17 - version 2.0.1
|
4 |
* Fix - Ensure the configured business name is never empty when connecting to Facebook
|
5 |
|
1 |
*** Facebook for WooCommerce Changelog ***
|
2 |
|
3 |
+
2020.09.25 - version 2.0.2
|
4 |
+
* Tweak - Allow simple and variable products with zero/empty price to sync to Facebook
|
5 |
+
* Tweak - Use the bundle price for Product Bundles products with individually priced items
|
6 |
+
* Fix - Update connection parameters to use an array to pass the Messenger domain
|
7 |
+
* Fix - Ensure out-of-stock products are marked as such in Facebook when the feed file replacement is run
|
8 |
+
* Fix - Address a potential error when connecting from a site whose title contains special characters
|
9 |
+
|
10 |
2020.08.17 - version 2.0.1
|
11 |
* Fix - Ensure the configured business name is never empty when connecting to Facebook
|
12 |
|
class-wc-facebookcommerce.php
CHANGED
@@ -21,7 +21,7 @@ if ( ! class_exists( 'WC_Facebookcommerce' ) ) :
|
|
21 |
|
22 |
|
23 |
/** @var string the plugin version */
|
24 |
-
const VERSION = '2.0.
|
25 |
|
26 |
/** @var string for backwards compatibility TODO: remove this in v2.0.0 {CW 2020-02-06} */
|
27 |
const PLUGIN_VERSION = self::VERSION;
|
21 |
|
22 |
|
23 |
/** @var string the plugin version */
|
24 |
+
const VERSION = '2.0.2';
|
25 |
|
26 |
/** @var string for backwards compatibility TODO: remove this in v2.0.0 {CW 2020-02-06} */
|
27 |
const PLUGIN_VERSION = self::VERSION;
|
facebook-commerce.php
CHANGED
@@ -572,11 +572,11 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
572 |
global $post;
|
573 |
|
574 |
$woo_product = new WC_Facebook_Product( $post->ID );
|
575 |
-
$fb_product_group_id =
|
576 |
-
|
577 |
-
|
578 |
-
$woo_product
|
579 |
-
|
580 |
|
581 |
?>
|
582 |
<span id="fb_metadata">
|
@@ -896,6 +896,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
896 |
case 'simple':
|
897 |
case 'booking':
|
898 |
case 'external':
|
|
|
899 |
$this->on_simple_product_publish( $wp_id );
|
900 |
break;
|
901 |
|
@@ -964,7 +965,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
964 |
* @see ajax_delete_fb_product()
|
965 |
*/
|
966 |
if ( ( ! is_ajax() || ! isset( $_POST['action'] ) || 'ajax_delete_fb_product' !== $_POST['action'] )
|
967 |
-
&& ! Products::
|
968 |
|
969 |
return;
|
970 |
}
|
@@ -1017,6 +1018,10 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1017 |
return;
|
1018 |
}
|
1019 |
|
|
|
|
|
|
|
|
|
1020 |
$visibility = $new_status === 'publish' ? self::FB_SHOP_PRODUCT_VISIBLE : self::FB_SHOP_PRODUCT_HIDDEN;
|
1021 |
|
1022 |
$product = wc_get_product( $post->ID );
|
@@ -1027,16 +1032,30 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1027 |
// variations before it gets called with the variable product. As a result, Products::product_should_be_synced()
|
1028 |
// always returns false for the variable product (since all children are in the trash at that point).
|
1029 |
// This causes update_fb_visibility() to be called on simple products and product variations only.
|
1030 |
-
if ( ! $product instanceof \WC_Product || ! Products::
|
1031 |
return;
|
1032 |
}
|
1033 |
|
1034 |
-
|
1035 |
-
|
1036 |
-
|
1037 |
-
|
1038 |
-
|
1039 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1040 |
}
|
1041 |
|
1042 |
|
@@ -1209,30 +1228,19 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1209 |
/**
|
1210 |
* Determines whether the product with the given ID should be synced.
|
1211 |
*
|
1212 |
-
* TODO: can we move this logic into Products::product_should_be_synced()? {WV 2020-05-22}
|
1213 |
-
*
|
1214 |
* @since 2.0.0
|
1215 |
*
|
1216 |
* @param \WC_Product|false $product product object
|
1217 |
*/
|
1218 |
public function product_should_be_synced( $product ) {
|
1219 |
|
1220 |
-
$should_be_synced =
|
1221 |
-
|
1222 |
-
if ( ! $this->is_product_sync_enabled() ) {
|
1223 |
-
$should_be_synced = false;
|
1224 |
-
}
|
1225 |
|
1226 |
// can't sync if we don't have a valid product object
|
1227 |
if ( $should_be_synced && ! $product instanceof \WC_Product ) {
|
1228 |
$should_be_synced = false;
|
1229 |
}
|
1230 |
|
1231 |
-
// only published product should be synced
|
1232 |
-
if ( $should_be_synced && 'publish' !== get_post_status( $product->get_id() ) ) {
|
1233 |
-
$should_be_synced = false;
|
1234 |
-
}
|
1235 |
-
|
1236 |
// make sure the given product is enabled for sync
|
1237 |
if ( $should_be_synced && ! Products::product_should_be_synced( $product ) ) {
|
1238 |
$should_be_synced = false;
|
@@ -1310,10 +1318,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
1310 |
|
1311 |
function create_product_item( $woo_product, $retailer_id, $product_group_id ) {
|
1312 |
|
1313 |
-
$product_data
|
1314 |
-
if ( ! $product_data['price'] ) {
|
1315 |
-
return 0;
|
1316 |
-
}
|
1317 |
|
1318 |
$product_result = $this->check_api_result(
|
1319 |
$this->fbgraph->create_product_item(
|
@@ -3337,7 +3342,7 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3337 |
public function on_quick_and_bulk_edit_save( $product ) {
|
3338 |
|
3339 |
// bail if not a product or product is not enabled for sync
|
3340 |
-
if ( ! $product instanceof \WC_Product || ! Products::
|
3341 |
return;
|
3342 |
}
|
3343 |
|
@@ -3383,12 +3388,6 @@ class WC_Facebookcommerce_Integration extends WC_Integration {
|
|
3383 |
// if the product with ID equal to $wp_id is variable, $woo_product will be the first child
|
3384 |
$woo_product = new WC_Facebook_Product( current( $products ) );
|
3385 |
|
3386 |
-
// This is a generalized function used elsewhere
|
3387 |
-
// Cannot call is_hidden for VC_Product_Variable Object
|
3388 |
-
if ( $woo_product->is_hidden() ) {
|
3389 |
-
return null;
|
3390 |
-
}
|
3391 |
-
|
3392 |
$fb_retailer_id = WC_Facebookcommerce_Utils::get_fb_retailer_id( $woo_product );
|
3393 |
|
3394 |
$product_fbid_result = $this->fbgraph->get_facebook_id(
|
572 |
global $post;
|
573 |
|
574 |
$woo_product = new WC_Facebook_Product( $post->ID );
|
575 |
+
$fb_product_group_id = null;
|
576 |
+
|
577 |
+
if ( $woo_product->woo_product instanceof \WC_Product && Products::product_should_be_synced( $woo_product->woo_product ) ) {
|
578 |
+
$fb_product_group_id = $this->get_product_fbid( self::FB_PRODUCT_GROUP_ID, $post->ID, $woo_product );
|
579 |
+
}
|
580 |
|
581 |
?>
|
582 |
<span id="fb_metadata">
|
896 |
case 'simple':
|
897 |
case 'booking':
|
898 |
case 'external':
|
899 |
+
case 'composite':
|
900 |
$this->on_simple_product_publish( $wp_id );
|
901 |
break;
|
902 |
|
965 |
* @see ajax_delete_fb_product()
|
966 |
*/
|
967 |
if ( ( ! is_ajax() || ! isset( $_POST['action'] ) || 'ajax_delete_fb_product' !== $_POST['action'] )
|
968 |
+
&& ! Products::published_product_should_be_synced( $product ) ) {
|
969 |
|
970 |
return;
|
971 |
}
|
1018 |
return;
|
1019 |
}
|
1020 |
|
1021 |
+
if ( ! $this->should_update_visibility_for_product_status_change( $new_status, $old_status ) ) {
|
1022 |
+
return;
|
1023 |
+
}
|
1024 |
+
|
1025 |
$visibility = $new_status === 'publish' ? self::FB_SHOP_PRODUCT_VISIBLE : self::FB_SHOP_PRODUCT_HIDDEN;
|
1026 |
|
1027 |
$product = wc_get_product( $post->ID );
|
1032 |
// variations before it gets called with the variable product. As a result, Products::product_should_be_synced()
|
1033 |
// always returns false for the variable product (since all children are in the trash at that point).
|
1034 |
// This causes update_fb_visibility() to be called on simple products and product variations only.
|
1035 |
+
if ( ! $product instanceof \WC_Product || ! Products::published_product_should_be_synced( $product ) ) {
|
1036 |
return;
|
1037 |
}
|
1038 |
|
1039 |
+
$this->update_fb_visibility( $product, $visibility );
|
1040 |
+
}
|
1041 |
+
|
1042 |
+
|
1043 |
+
/**
|
1044 |
+
* Determines whether the product visibility needs to be updated for the given status change.
|
1045 |
+
*
|
1046 |
+
* Change from publish status -> unpublish status (e.g. trash, draft, etc.)
|
1047 |
+
* Change from trash status -> publish status
|
1048 |
+
* No need to update for change from trash <-> unpublish status
|
1049 |
+
*
|
1050 |
+
* @since 2.0.2
|
1051 |
+
*
|
1052 |
+
* @param string $new_status
|
1053 |
+
* @param string $old_status
|
1054 |
+
* @return bool
|
1055 |
+
*/
|
1056 |
+
private function should_update_visibility_for_product_status_change( $new_status, $old_status ) {
|
1057 |
+
|
1058 |
+
return ( $old_status === 'publish' && $new_status !== 'publish' ) || ( $old_status === 'trash' && $new_status === 'publish' );
|
1059 |
}
|
1060 |
|
1061 |
|
1228 |
/**
|
1229 |
* Determines whether the product with the given ID should be synced.
|
1230 |
*
|
|
|
|
|
1231 |
* @since 2.0.0
|
1232 |
*
|
1233 |
* @param \WC_Product|false $product product object
|
1234 |
*/
|
1235 |
public function product_should_be_synced( $product ) {
|
1236 |
|
1237 |
+
$should_be_synced = $this->is_product_sync_enabled();
|
|
|
|
|
|
|
|
|
1238 |
|
1239 |
// can't sync if we don't have a valid product object
|
1240 |
if ( $should_be_synced && ! $product instanceof \WC_Product ) {
|
1241 |
$should_be_synced = false;
|
1242 |
}
|
1243 |
|
|
|
|
|
|
|
|
|
|
|
1244 |
// make sure the given product is enabled for sync
|
1245 |
if ( $should_be_synced && ! Products::product_should_be_synced( $product ) ) {
|
1246 |
$should_be_synced = false;
|
1318 |
|
1319 |
function create_product_item( $woo_product, $retailer_id, $product_group_id ) {
|
1320 |
|
1321 |
+
$product_data = $woo_product->prepare_product( $retailer_id );
|
|
|
|
|
|
|
1322 |
|
1323 |
$product_result = $this->check_api_result(
|
1324 |
$this->fbgraph->create_product_item(
|
3342 |
public function on_quick_and_bulk_edit_save( $product ) {
|
3343 |
|
3344 |
// bail if not a product or product is not enabled for sync
|
3345 |
+
if ( ! $product instanceof \WC_Product || ! Products::published_product_should_be_synced( $product ) ) {
|
3346 |
return;
|
3347 |
}
|
3348 |
|
3388 |
// if the product with ID equal to $wp_id is variable, $woo_product will be the first child
|
3389 |
$woo_product = new WC_Facebook_Product( current( $products ) );
|
3390 |
|
|
|
|
|
|
|
|
|
|
|
|
|
3391 |
$fb_retailer_id = WC_Facebookcommerce_Utils::get_fb_retailer_id( $woo_product );
|
3392 |
|
3393 |
$product_fbid_result = $this->fbgraph->get_facebook_id(
|
facebook-for-woocommerce.php
CHANGED
@@ -10,10 +10,10 @@
|
|
10 |
* Description: Grow your business on Facebook! Use this official plugin to help sell more of your products using Facebook. After completing the setup, you'll be ready to create ads that promote your products and you can also create a shop section on your Page where customers can browse your products on Facebook.
|
11 |
* Author: Facebook
|
12 |
* Author URI: https://www.facebook.com/
|
13 |
-
* Version: 2.0.
|
14 |
* Text Domain: facebook-for-woocommerce
|
15 |
* WC requires at least: 3.5.0
|
16 |
-
* WC tested up to: 4.
|
17 |
*
|
18 |
* @package FacebookCommerce
|
19 |
*/
|
10 |
* Description: Grow your business on Facebook! Use this official plugin to help sell more of your products using Facebook. After completing the setup, you'll be ready to create ads that promote your products and you can also create a shop section on your Page where customers can browse your products on Facebook.
|
11 |
* Author: Facebook
|
12 |
* Author URI: https://www.facebook.com/
|
13 |
+
* Version: 2.0.2
|
14 |
* Text Domain: facebook-for-woocommerce
|
15 |
* WC requires at least: 3.5.0
|
16 |
+
* WC tested up to: 4.5.2
|
17 |
*
|
18 |
* @package FacebookCommerce
|
19 |
*/
|
i18n/languages/facebook-for-woocommerce.pot
CHANGED
@@ -2,10 +2,10 @@
|
|
2 |
# This file is distributed under the same license as the Facebook for WooCommerce package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
-
"Project-Id-Version: Facebook for WooCommerce 2.0.
|
6 |
"Report-Msgid-Bugs-To: "
|
7 |
"https://woocommerce.com/my-account/marketplace-ticket-form/\n"
|
8 |
-
"POT-Creation-Date: 2020-
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=utf-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
@@ -87,45 +87,45 @@ msgstr ""
|
|
87 |
msgid "This product is not yet synced to Facebook."
|
88 |
msgstr ""
|
89 |
|
90 |
-
#: facebook-commerce.php:
|
91 |
msgid "Nothing to update for product group for %1$s"
|
92 |
msgstr ""
|
93 |
|
94 |
-
#: facebook-commerce.php:
|
95 |
#. translators: Placeholders %1$s - original error message from Facebook API
|
96 |
msgid "There was an issue connecting to the Facebook API: %1$s"
|
97 |
msgstr ""
|
98 |
|
99 |
-
#: facebook-commerce.php:
|
100 |
msgid "Your connection has expired."
|
101 |
msgstr ""
|
102 |
|
103 |
-
#: facebook-commerce.php:
|
104 |
msgid ""
|
105 |
"Please click Manage connection > Advanced Options > Update Token to refresh "
|
106 |
"your connection to Facebook."
|
107 |
msgstr ""
|
108 |
|
109 |
-
#: facebook-commerce.php:
|
110 |
#. translators: Placeholders %s - error message
|
111 |
msgid "There was an error trying to sync the products to Facebook. %s"
|
112 |
msgstr ""
|
113 |
|
114 |
-
#: facebook-commerce.php:
|
115 |
msgid "Product sync is disabled."
|
116 |
msgstr ""
|
117 |
|
118 |
-
#: facebook-commerce.php:
|
119 |
msgid "The plugin is not configured or the Catalog ID is missing."
|
120 |
msgstr ""
|
121 |
|
122 |
-
#: facebook-commerce.php:
|
123 |
msgid ""
|
124 |
"A product sync is in progress. Please wait until the sync finishes before "
|
125 |
"starting a new one."
|
126 |
msgstr ""
|
127 |
|
128 |
-
#: facebook-commerce.php:
|
129 |
msgid ""
|
130 |
"We've detected that your Facebook Product Catalog is no longer valid. This "
|
131 |
"may happen if it was deleted, but could also be a temporary error. If the "
|
@@ -133,33 +133,33 @@ msgid ""
|
|
133 |
"and setup the plugin again."
|
134 |
msgstr ""
|
135 |
|
136 |
-
#: facebook-commerce.php:
|
137 |
msgid "We couldn't create the feed or upload the product information."
|
138 |
msgstr ""
|
139 |
|
140 |
-
#: facebook-commerce.php:
|
141 |
msgid "Hi! We're here to answer any questions you may have."
|
142 |
msgstr ""
|
143 |
|
144 |
-
#: facebook-commerce.php:
|
145 |
msgid "Facebook for WooCommerce error:"
|
146 |
msgstr ""
|
147 |
|
148 |
-
#: facebook-commerce.php:
|
149 |
msgid ""
|
150 |
"There was an error trying to retrieve information about the Facebook page: "
|
151 |
"%s"
|
152 |
msgstr ""
|
153 |
|
154 |
-
#: facebook-commerce.php:
|
155 |
msgid "Get started with Messenger Customer Chat"
|
156 |
msgstr ""
|
157 |
|
158 |
-
#: facebook-commerce.php:
|
159 |
msgid "Get started with Instagram Shopping"
|
160 |
msgstr ""
|
161 |
|
162 |
-
#: facebook-commerce.php:
|
163 |
#. translators: Placeholders %1$s - original error message from Facebook API
|
164 |
msgid "There was an issue connecting to the Facebook API: %s"
|
165 |
msgstr ""
|
@@ -608,15 +608,15 @@ msgstr ""
|
|
608 |
msgid "Uninstall unsuccessful. Please try again."
|
609 |
msgstr ""
|
610 |
|
611 |
-
#: includes/Products/Sync/Background.php:
|
612 |
msgid "Job data key \"%s\" not set"
|
613 |
msgstr ""
|
614 |
|
615 |
-
#: includes/Products/Sync/Background.php:
|
616 |
msgid "Job data key \"%s\" is not an array"
|
617 |
msgstr ""
|
618 |
|
619 |
-
#: includes/Products/Sync/Background.php:
|
620 |
msgid ""
|
621 |
"There was an error trying sync products using the Catalog Batch API for job "
|
622 |
"%s: %s"
|
@@ -638,19 +638,19 @@ msgstr ""
|
|
638 |
msgid "Dismiss"
|
639 |
msgstr ""
|
640 |
|
641 |
-
#: includes/fbproductfeed.php:
|
642 |
msgid "Could not create product catalog feed directory"
|
643 |
msgstr ""
|
644 |
|
645 |
-
#: includes/fbproductfeed.php:
|
646 |
msgid "Could not open the product catalog temporary feed file for writing"
|
647 |
msgstr ""
|
648 |
|
649 |
-
#: includes/fbproductfeed.php:
|
650 |
msgid "Could not open the product catalog feed file for writing"
|
651 |
msgstr ""
|
652 |
|
653 |
-
#: includes/fbproductfeed.php:
|
654 |
msgid "Could not rename the product catalog feed file"
|
655 |
msgstr ""
|
656 |
|
2 |
# This file is distributed under the same license as the Facebook for WooCommerce package.
|
3 |
msgid ""
|
4 |
msgstr ""
|
5 |
+
"Project-Id-Version: Facebook for WooCommerce 2.0.2\n"
|
6 |
"Report-Msgid-Bugs-To: "
|
7 |
"https://woocommerce.com/my-account/marketplace-ticket-form/\n"
|
8 |
+
"POT-Creation-Date: 2020-09-26 00:08:41+00:00\n"
|
9 |
"MIME-Version: 1.0\n"
|
10 |
"Content-Type: text/plain; charset=utf-8\n"
|
11 |
"Content-Transfer-Encoding: 8bit\n"
|
87 |
msgid "This product is not yet synced to Facebook."
|
88 |
msgstr ""
|
89 |
|
90 |
+
#: facebook-commerce.php:1374
|
91 |
msgid "Nothing to update for product group for %1$s"
|
92 |
msgstr ""
|
93 |
|
94 |
+
#: facebook-commerce.php:1640
|
95 |
#. translators: Placeholders %1$s - original error message from Facebook API
|
96 |
msgid "There was an issue connecting to the Facebook API: %1$s"
|
97 |
msgstr ""
|
98 |
|
99 |
+
#: facebook-commerce.php:1977
|
100 |
msgid "Your connection has expired."
|
101 |
msgstr ""
|
102 |
|
103 |
+
#: facebook-commerce.php:1977
|
104 |
msgid ""
|
105 |
"Please click Manage connection > Advanced Options > Update Token to refresh "
|
106 |
"your connection to Facebook."
|
107 |
msgstr ""
|
108 |
|
109 |
+
#: facebook-commerce.php:1984
|
110 |
#. translators: Placeholders %s - error message
|
111 |
msgid "There was an error trying to sync the products to Facebook. %s"
|
112 |
msgstr ""
|
113 |
|
114 |
+
#: facebook-commerce.php:2007 facebook-commerce.php:2180
|
115 |
msgid "Product sync is disabled."
|
116 |
msgstr ""
|
117 |
|
118 |
+
#: facebook-commerce.php:2014 facebook-commerce.php:2187
|
119 |
msgid "The plugin is not configured or the Catalog ID is missing."
|
120 |
msgstr ""
|
121 |
|
122 |
+
#: facebook-commerce.php:2037
|
123 |
msgid ""
|
124 |
"A product sync is in progress. Please wait until the sync finishes before "
|
125 |
"starting a new one."
|
126 |
msgstr ""
|
127 |
|
128 |
+
#: facebook-commerce.php:2049 facebook-commerce.php:2201
|
129 |
msgid ""
|
130 |
"We've detected that your Facebook Product Catalog is no longer valid. This "
|
131 |
"may happen if it was deleted, but could also be a temporary error. If the "
|
133 |
"and setup the plugin again."
|
134 |
msgstr ""
|
135 |
|
136 |
+
#: facebook-commerce.php:2225
|
137 |
msgid "We couldn't create the feed or upload the product information."
|
138 |
msgstr ""
|
139 |
|
140 |
+
#: facebook-commerce.php:2692
|
141 |
msgid "Hi! We're here to answer any questions you may have."
|
142 |
msgstr ""
|
143 |
|
144 |
+
#: facebook-commerce.php:3036
|
145 |
msgid "Facebook for WooCommerce error:"
|
146 |
msgstr ""
|
147 |
|
148 |
+
#: facebook-commerce.php:3118
|
149 |
msgid ""
|
150 |
"There was an error trying to retrieve information about the Facebook page: "
|
151 |
"%s"
|
152 |
msgstr ""
|
153 |
|
154 |
+
#: facebook-commerce.php:3169
|
155 |
msgid "Get started with Messenger Customer Chat"
|
156 |
msgstr ""
|
157 |
|
158 |
+
#: facebook-commerce.php:3170
|
159 |
msgid "Get started with Instagram Shopping"
|
160 |
msgstr ""
|
161 |
|
162 |
+
#: facebook-commerce.php:3405
|
163 |
#. translators: Placeholders %1$s - original error message from Facebook API
|
164 |
msgid "There was an issue connecting to the Facebook API: %s"
|
165 |
msgstr ""
|
608 |
msgid "Uninstall unsuccessful. Please try again."
|
609 |
msgstr ""
|
610 |
|
611 |
+
#: includes/Products/Sync/Background.php:65
|
612 |
msgid "Job data key \"%s\" not set"
|
613 |
msgstr ""
|
614 |
|
615 |
+
#: includes/Products/Sync/Background.php:69
|
616 |
msgid "Job data key \"%s\" is not an array"
|
617 |
msgstr ""
|
618 |
|
619 |
+
#: includes/Products/Sync/Background.php:153
|
620 |
msgid ""
|
621 |
"There was an error trying sync products using the Catalog Batch API for job "
|
622 |
"%s: %s"
|
638 |
msgid "Dismiss"
|
639 |
msgstr ""
|
640 |
|
641 |
+
#: includes/fbproductfeed.php:484
|
642 |
msgid "Could not create product catalog feed directory"
|
643 |
msgstr ""
|
644 |
|
645 |
+
#: includes/fbproductfeed.php:550
|
646 |
msgid "Could not open the product catalog temporary feed file for writing"
|
647 |
msgstr ""
|
648 |
|
649 |
+
#: includes/fbproductfeed.php:557
|
650 |
msgid "Could not open the product catalog feed file for writing"
|
651 |
msgstr ""
|
652 |
|
653 |
+
#: includes/fbproductfeed.php:601
|
654 |
msgid "Could not rename the product catalog feed file"
|
655 |
msgstr ""
|
656 |
|
includes/Handlers/Connection.php
CHANGED
@@ -449,16 +449,32 @@ class Connection {
|
|
449 |
|
450 |
if ( ! is_string( $this->external_business_id ) ) {
|
451 |
|
452 |
-
$
|
453 |
-
|
454 |
-
if ( ! is_string( $
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
455 |
|
456 |
-
$
|
457 |
|
458 |
-
update_option( self::OPTION_EXTERNAL_BUSINESS_ID, $
|
459 |
}
|
460 |
|
461 |
-
$this->external_business_id = $
|
462 |
}
|
463 |
|
464 |
/**
|
@@ -653,7 +669,9 @@ class Connection {
|
|
653 |
|
654 |
$parameters['business_config']['messenger_chat'] = [
|
655 |
'enabled' => true,
|
656 |
-
'domains' =>
|
|
|
|
|
657 |
];
|
658 |
}
|
659 |
|
449 |
|
450 |
if ( ! is_string( $this->external_business_id ) ) {
|
451 |
|
452 |
+
$external_id = get_option( self::OPTION_EXTERNAL_BUSINESS_ID );
|
453 |
+
|
454 |
+
if ( ! is_string( $external_id ) ) {
|
455 |
+
|
456 |
+
/**
|
457 |
+
* Filters the shop's business external ID.
|
458 |
+
*
|
459 |
+
* This is passed to Facebook when connecting.
|
460 |
+
* Should be non-empty and without special characters, otherwise the ID will be obtained from the site URL as fallback.
|
461 |
+
*
|
462 |
+
* @since 2.0.0
|
463 |
+
*
|
464 |
+
* @param string $external_id the shop's business external ID
|
465 |
+
*/
|
466 |
+
$external_id = sanitize_key( (string) apply_filters( 'wc_facebook_connection_business_id', get_bloginfo( 'name' ) ) );
|
467 |
+
|
468 |
+
if ( empty( $external_id ) ) {
|
469 |
+
$external_id = sanitize_key( str_replace( [ 'http', 'https', 'www' ], '', get_bloginfo( 'url' ) ) );
|
470 |
+
}
|
471 |
|
472 |
+
$external_id = uniqid( sprintf( '%s-', $external_id ), false );
|
473 |
|
474 |
+
update_option( self::OPTION_EXTERNAL_BUSINESS_ID, $external_id );
|
475 |
}
|
476 |
|
477 |
+
$this->external_business_id = $external_id;
|
478 |
}
|
479 |
|
480 |
/**
|
669 |
|
670 |
$parameters['business_config']['messenger_chat'] = [
|
671 |
'enabled' => true,
|
672 |
+
'domains' => [
|
673 |
+
home_url( '/' ),
|
674 |
+
],
|
675 |
];
|
676 |
}
|
677 |
|
includes/Integrations/Bookings.php
ADDED
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
namespace SkyVerge\WooCommerce\Facebook\Integrations;
|
12 |
+
|
13 |
+
defined( 'ABSPATH' ) or exit;
|
14 |
+
|
15 |
+
/**
|
16 |
+
* Integration with WooCommerce Bookings.
|
17 |
+
*
|
18 |
+
* @since 2.0.0-dev.1
|
19 |
+
*/
|
20 |
+
class Bookings {
|
21 |
+
|
22 |
+
|
23 |
+
/**
|
24 |
+
* Integration constructor.
|
25 |
+
*
|
26 |
+
* @since 2.0.0-dev.3
|
27 |
+
*/
|
28 |
+
public function __construct() {
|
29 |
+
|
30 |
+
add_action( 'init', [ $this, 'add_hooks' ] );
|
31 |
+
}
|
32 |
+
|
33 |
+
|
34 |
+
/**
|
35 |
+
* Adds integration hooks.
|
36 |
+
*
|
37 |
+
* @since 2.0.0-dev.3
|
38 |
+
*/
|
39 |
+
public function add_hooks() {
|
40 |
+
|
41 |
+
if ( facebook_for_woocommerce()->is_plugin_active( 'woocommerce-bookings.php') ) {
|
42 |
+
add_filter( 'wc_facebook_product_price', [ $this, 'get_product_price' ], 10, 3 );
|
43 |
+
}
|
44 |
+
}
|
45 |
+
|
46 |
+
|
47 |
+
/**
|
48 |
+
* Filters the product price user for Facebook sync for Bookable products.
|
49 |
+
*
|
50 |
+
* @internal
|
51 |
+
*
|
52 |
+
* @since 2.0.0-dev.3
|
53 |
+
*
|
54 |
+
* @param int $price product price in cents
|
55 |
+
* @param float $facebook_price user defined facebook price
|
56 |
+
* @param \WC_Product $product product object
|
57 |
+
* @return int
|
58 |
+
*/
|
59 |
+
public function get_product_price( $price, $facebook_price, $product ) {
|
60 |
+
|
61 |
+
if ( ! $facebook_price && $product instanceof \WC_Product && $this->is_bookable_product( $product ) ) {
|
62 |
+
|
63 |
+
$product = new \WC_Product_Booking( $product );
|
64 |
+
$display_cost = is_callable( [ $product, 'get_display_cost' ] ) ? $product->get_display_cost() : 0;
|
65 |
+
|
66 |
+
$price = (int) round( wc_get_price_to_display( $product, [ 'price' => $display_cost ] ) * 100 );
|
67 |
+
}
|
68 |
+
|
69 |
+
return $price;
|
70 |
+
}
|
71 |
+
|
72 |
+
|
73 |
+
/**
|
74 |
+
* Determines whether the current product is a WooCommerce Bookings product.
|
75 |
+
*
|
76 |
+
* @since 2.0.0-dev.3
|
77 |
+
*
|
78 |
+
* @param \WC_Product $product product object
|
79 |
+
* @return bool
|
80 |
+
*/
|
81 |
+
private function is_bookable_product( \WC_Product $product ) {
|
82 |
+
|
83 |
+
return class_exists( 'WC_Product_Booking' ) && is_callable( 'is_wc_booking_product' ) && is_wc_booking_product( $product );
|
84 |
+
}
|
85 |
+
|
86 |
+
|
87 |
+
}
|
88 |
+
|
includes/Integrations/Integrations.php
CHANGED
@@ -53,6 +53,7 @@ class Integrations {
|
|
53 |
|
54 |
$registered_integrations = [
|
55 |
'WC_Facebook_WPML_Injector' => '/includes/fbwpml.php',
|
|
|
56 |
];
|
57 |
|
58 |
foreach ( $registered_integrations as $class_name => $path ) {
|
53 |
|
54 |
$registered_integrations = [
|
55 |
'WC_Facebook_WPML_Injector' => '/includes/fbwpml.php',
|
56 |
+
Bookings::class => '/includes/Integrations/Bookings.php',
|
57 |
];
|
58 |
|
59 |
foreach ( $registered_integrations as $class_name => $path ) {
|
includes/Products.php
CHANGED
@@ -10,6 +10,8 @@
|
|
10 |
|
11 |
namespace SkyVerge\WooCommerce\Facebook;
|
12 |
|
|
|
|
|
13 |
defined( 'ABSPATH' ) or exit;
|
14 |
|
15 |
/**
|
@@ -162,21 +164,58 @@ class Products {
|
|
162 |
/**
|
163 |
* Determines whether the given product should be synced.
|
164 |
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
165 |
* If a product is enabled for sync, but belongs to an excluded term, it will return as excluded from sync:
|
166 |
* @see Products::is_sync_enabled_for_product()
|
167 |
* @see Products::is_sync_excluded_for_product_terms()
|
168 |
*
|
169 |
-
* @since
|
170 |
*
|
171 |
* @param \WC_Product $product
|
172 |
* @return bool
|
173 |
*/
|
174 |
-
public static function
|
|
|
|
|
175 |
|
176 |
// define the product to check terms on
|
177 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
178 |
|
179 |
-
|
|
|
|
|
|
|
|
|
|
|
180 |
}
|
181 |
|
182 |
|
@@ -338,4 +377,56 @@ class Products {
|
|
338 |
}
|
339 |
|
340 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
341 |
}
|
10 |
|
11 |
namespace SkyVerge\WooCommerce\Facebook;
|
12 |
|
13 |
+
use WC_Facebook_Product;
|
14 |
+
|
15 |
defined( 'ABSPATH' ) or exit;
|
16 |
|
17 |
/**
|
164 |
/**
|
165 |
* Determines whether the given product should be synced.
|
166 |
*
|
167 |
+
* @see Products::published_product_should_be_synced()
|
168 |
+
*
|
169 |
+
* @since 1.10.0
|
170 |
+
*
|
171 |
+
* @param \WC_Product $product
|
172 |
+
* @return bool
|
173 |
+
*/
|
174 |
+
public static function product_should_be_synced( \WC_Product $product ) {
|
175 |
+
|
176 |
+
return 'publish' === $product->get_status() && self::published_product_should_be_synced( $product );
|
177 |
+
}
|
178 |
+
|
179 |
+
|
180 |
+
/**
|
181 |
+
* Determines whether the given product should be synced assuming the product is published.
|
182 |
+
*
|
183 |
* If a product is enabled for sync, but belongs to an excluded term, it will return as excluded from sync:
|
184 |
* @see Products::is_sync_enabled_for_product()
|
185 |
* @see Products::is_sync_excluded_for_product_terms()
|
186 |
*
|
187 |
+
* @since 2.0.0-dev.1
|
188 |
*
|
189 |
* @param \WC_Product $product
|
190 |
* @return bool
|
191 |
*/
|
192 |
+
public static function published_product_should_be_synced( \WC_Product $product ) {
|
193 |
+
|
194 |
+
$should_sync = self::is_sync_enabled_for_product( $product );
|
195 |
|
196 |
// define the product to check terms on
|
197 |
+
if ( $should_sync ) {
|
198 |
+
$terms_product = $product->is_type( 'variation' ) ? wc_get_product( $product->get_parent_id() ) : $product;
|
199 |
+
} else {
|
200 |
+
$terms_product = null;
|
201 |
+
}
|
202 |
+
|
203 |
+
// allow simple or variable products (and their variations) with zero or empty price - exclude other product types with zero or empty price
|
204 |
+
if ( $should_sync && ( ! $terms_product || ( ! self::get_product_price( $product ) && ! in_array( $terms_product->get_type(), [ 'simple', 'variable' ] ) ) ) ) {
|
205 |
+
$should_sync = false;
|
206 |
+
}
|
207 |
+
|
208 |
+
// exclude products that are excluded from the store catalog or from search results
|
209 |
+
if ( $should_sync && ( ! $terms_product || has_term( [ 'exclude-from-catalog', 'exclude-from-search' ], 'product_visibility', $terms_product->get_id() ) ) ) {
|
210 |
+
$should_sync = false;
|
211 |
+
}
|
212 |
|
213 |
+
// exclude products that belong to one of the excluded terms
|
214 |
+
if ( $should_sync && ( ! $terms_product || self::is_sync_excluded_for_product_terms( $terms_product ) ) ) {
|
215 |
+
$should_sync = false;
|
216 |
+
}
|
217 |
+
|
218 |
+
return $should_sync;
|
219 |
}
|
220 |
|
221 |
|
377 |
}
|
378 |
|
379 |
|
380 |
+
/**
|
381 |
+
* Gets the product price used for Facebook sync.
|
382 |
+
*
|
383 |
+
* TODO: Consider adding memoization, but ensure we can protect the implementation against price changes during the same request {WV-2020-08-20}
|
384 |
+
* See https://github.com/facebookincubator/facebook-for-woocommerce/pull/1468
|
385 |
+
*
|
386 |
+
* @since 2.0.0-dev.1
|
387 |
+
*
|
388 |
+
* @param int $price product price in cents
|
389 |
+
* @param \WC_Product $product product object
|
390 |
+
* @return int
|
391 |
+
*/
|
392 |
+
public static function get_product_price( \WC_Product $product ) {
|
393 |
+
|
394 |
+
$facebook_price = $product->get_meta( WC_Facebook_Product::FB_PRODUCT_PRICE );
|
395 |
+
|
396 |
+
// use the user defined Facebook price if set
|
397 |
+
if ( is_numeric( $facebook_price ) ) {
|
398 |
+
|
399 |
+
$price = $facebook_price;
|
400 |
+
|
401 |
+
} elseif ( class_exists( 'WC_Product_Composite' ) && $product instanceof \WC_Product_Composite ) {
|
402 |
+
|
403 |
+
$price = get_option( 'woocommerce_tax_display_shop' ) === 'incl' ? $product->get_composite_price_including_tax() : $product->get_composite_price();
|
404 |
+
|
405 |
+
} elseif ( class_exists( 'WC_Product_Bundle' )
|
406 |
+
&& empty( $product->get_regular_price() )
|
407 |
+
&& 'bundle' === $product->get_type() ) {
|
408 |
+
|
409 |
+
// if product is a product bundle with individually priced items, we rely on their pricing
|
410 |
+
$price = wc_get_price_to_display( $product, [ 'price' => $product->get_bundle_price() ] );
|
411 |
+
|
412 |
+
} else {
|
413 |
+
|
414 |
+
$price = wc_get_price_to_display( $product, [ 'price' => $product->get_regular_price() ] );
|
415 |
+
}
|
416 |
+
|
417 |
+
$price = (int) ( $price ? round( $price * 100 ) : 0 );
|
418 |
+
|
419 |
+
/**
|
420 |
+
* Filters the product price used for Facebook sync.
|
421 |
+
*
|
422 |
+
* @since 2.0.0-dev.1
|
423 |
+
*
|
424 |
+
* @param int $price product price in cents
|
425 |
+
* @param float $facebook_price user defined facebook price
|
426 |
+
* @param \WC_Product $product product object
|
427 |
+
*/
|
428 |
+
return (int) apply_filters( 'wc_facebook_product_price', $price, (float) $facebook_price, $product );
|
429 |
+
}
|
430 |
+
|
431 |
+
|
432 |
}
|
includes/Products/Sync.php
CHANGED
@@ -103,26 +103,8 @@ class Sync {
|
|
103 |
// remove parent products because those can't be represented as Product Items
|
104 |
$product_ids = array_diff( $product_ids, $parent_product_ids );
|
105 |
|
106 |
-
//
|
107 |
-
|
108 |
-
|
109 |
-
$woo_product = new \WC_Facebook_Product( $product_id );
|
110 |
-
|
111 |
-
if ( $woo_product->is_hidden() ) {
|
112 |
-
continue;
|
113 |
-
}
|
114 |
-
|
115 |
-
if ( get_option( 'woocommerce_hide_out_of_stock_items' ) === 'yes' && ! $woo_product->is_in_stock() ) {
|
116 |
-
continue;
|
117 |
-
}
|
118 |
-
|
119 |
-
// skip if not enabled for sync
|
120 |
-
if ( $woo_product->woo_product instanceof \WC_Product && ! Products::product_should_be_synced( $woo_product->woo_product ) ) {
|
121 |
-
continue;
|
122 |
-
}
|
123 |
-
|
124 |
-
$this->create_or_update_products( [ $product_id ] );
|
125 |
-
}
|
126 |
}
|
127 |
|
128 |
|
103 |
// remove parent products because those can't be represented as Product Items
|
104 |
$product_ids = array_diff( $product_ids, $parent_product_ids );
|
105 |
|
106 |
+
// queue up these IDs for sync. they will only be included in the final requests if they should be synced
|
107 |
+
$this->create_or_update_products( $product_ids );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
}
|
109 |
|
110 |
|
includes/Products/Sync/Background.php
CHANGED
@@ -12,6 +12,7 @@ namespace SkyVerge\WooCommerce\Facebook\Products\Sync;
|
|
12 |
|
13 |
defined( 'ABSPATH' ) or exit;
|
14 |
|
|
|
15 |
use SkyVerge\WooCommerce\Facebook\Products\Sync;
|
16 |
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
17 |
|
@@ -115,7 +116,9 @@ class Background extends Framework\SV_WP_Background_Job_Handler {
|
|
115 |
|
116 |
try {
|
117 |
|
118 |
-
$
|
|
|
|
|
119 |
|
120 |
} catch ( Framework\SV_WC_Plugin_Exception $e ) {
|
121 |
|
@@ -162,7 +165,7 @@ class Background extends Framework\SV_WP_Background_Job_Handler {
|
|
162 |
*
|
163 |
* @param mixed $item
|
164 |
* @param object|\stdClass $job
|
165 |
-
* @return array
|
166 |
* @throws Framework\SV_WC_Plugin_Exception
|
167 |
*/
|
168 |
public function process_item( $item, $job ) {
|
@@ -189,7 +192,7 @@ class Background extends Framework\SV_WP_Background_Job_Handler {
|
|
189 |
* @since 2.0.0
|
190 |
*
|
191 |
* @param string $prefixed_product_id prefixed product ID
|
192 |
-
* @return array
|
193 |
* @throws Framework\SV_WC_Plugin_Exception
|
194 |
*/
|
195 |
private function process_item_update( $prefixed_product_id ) {
|
@@ -201,33 +204,40 @@ class Background extends Framework\SV_WP_Background_Job_Handler {
|
|
201 |
throw new Framework\SV_WC_Plugin_Exception( "No product found with ID equal to {$product_id}." );
|
202 |
}
|
203 |
|
204 |
-
|
205 |
-
$product_data = $this->prepare_product_variation_data( $product );
|
206 |
-
} else {
|
207 |
-
$product_data = $this->prepare_product_data( $product );
|
208 |
-
}
|
209 |
|
210 |
-
|
211 |
-
$retailer_id = $product_data['retailer_id'];
|
212 |
|
213 |
-
|
214 |
-
|
|
|
|
|
|
|
215 |
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
221 |
|
222 |
-
|
223 |
-
* Filters the data that will be included in a UPDATE sync request.
|
224 |
-
*
|
225 |
-
* @since 2.0.0
|
226 |
-
*
|
227 |
-
* @param array $request request data
|
228 |
-
* @param \WC_Product $product product object
|
229 |
-
*/
|
230 |
-
return apply_filters( 'wc_facebook_sync_background_item_update_request', $request, $product );
|
231 |
}
|
232 |
|
233 |
|
12 |
|
13 |
defined( 'ABSPATH' ) or exit;
|
14 |
|
15 |
+
use SkyVerge\WooCommerce\Facebook\Products;
|
16 |
use SkyVerge\WooCommerce\Facebook\Products\Sync;
|
17 |
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
18 |
|
116 |
|
117 |
try {
|
118 |
|
119 |
+
if ( $request = $this->process_item( [ $item_id, $method ], $job ) ) {
|
120 |
+
$requests[] = $request;
|
121 |
+
}
|
122 |
|
123 |
} catch ( Framework\SV_WC_Plugin_Exception $e ) {
|
124 |
|
165 |
*
|
166 |
* @param mixed $item
|
167 |
* @param object|\stdClass $job
|
168 |
+
* @return array|null
|
169 |
* @throws Framework\SV_WC_Plugin_Exception
|
170 |
*/
|
171 |
public function process_item( $item, $job ) {
|
192 |
* @since 2.0.0
|
193 |
*
|
194 |
* @param string $prefixed_product_id prefixed product ID
|
195 |
+
* @return array|null
|
196 |
* @throws Framework\SV_WC_Plugin_Exception
|
197 |
*/
|
198 |
private function process_item_update( $prefixed_product_id ) {
|
204 |
throw new Framework\SV_WC_Plugin_Exception( "No product found with ID equal to {$product_id}." );
|
205 |
}
|
206 |
|
207 |
+
$request = null;
|
|
|
|
|
|
|
|
|
208 |
|
209 |
+
if ( ! Products::product_should_be_deleted( $product ) && Products::product_should_be_synced( $product ) ) {
|
|
|
210 |
|
211 |
+
if ( $product->is_type( 'variation' ) ) {
|
212 |
+
$product_data = $this->prepare_product_variation_data( $product );
|
213 |
+
} else {
|
214 |
+
$product_data = $this->prepare_product_data( $product );
|
215 |
+
}
|
216 |
|
217 |
+
// extract the retailer_id
|
218 |
+
$retailer_id = $product_data['retailer_id'];
|
219 |
+
|
220 |
+
// retailer_id cannot be included in the data object
|
221 |
+
unset( $product_data['retailer_id'] );
|
222 |
+
|
223 |
+
$request = [
|
224 |
+
'retailer_id' => $retailer_id,
|
225 |
+
'method' => Sync::ACTION_UPDATE,
|
226 |
+
'data' => $product_data,
|
227 |
+
];
|
228 |
+
|
229 |
+
/**
|
230 |
+
* Filters the data that will be included in a UPDATE sync request.
|
231 |
+
*
|
232 |
+
* @since 2.0.0
|
233 |
+
*
|
234 |
+
* @param array $request request data
|
235 |
+
* @param \WC_Product $product product object
|
236 |
+
*/
|
237 |
+
$request = apply_filters( 'wc_facebook_sync_background_item_update_request', $request, $product );
|
238 |
+
}
|
239 |
|
240 |
+
return $request;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
241 |
}
|
242 |
|
243 |
|
includes/fbproduct.php
CHANGED
@@ -124,46 +124,8 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
124 |
}
|
125 |
|
126 |
public function get_fb_price() {
|
127 |
-
// Cache the price in this object in case of multiple calls.
|
128 |
-
if ( $this->fb_price ) {
|
129 |
-
return $this->fb_price;
|
130 |
-
}
|
131 |
-
|
132 |
-
$price = get_post_meta(
|
133 |
-
$this->id,
|
134 |
-
self::FB_PRODUCT_PRICE,
|
135 |
-
true
|
136 |
-
);
|
137 |
|
138 |
-
|
139 |
-
return intval( round( $price * 100 ) );
|
140 |
-
}
|
141 |
-
|
142 |
-
// If product is composite product, we rely on their pricing.
|
143 |
-
if ( class_exists( 'WC_Product_Composite' )
|
144 |
-
&& $this->woo_product->get_type() === 'composite' ) {
|
145 |
-
$price = get_option( 'woocommerce_tax_display_shop' ) === 'incl'
|
146 |
-
? $this->woo_product->get_composite_price_including_tax()
|
147 |
-
: $this->woo_product->get_composite_price();
|
148 |
-
$this->fb_price = intval( round( $price * 100 ) );
|
149 |
-
return $this->fb_price;
|
150 |
-
}
|
151 |
-
|
152 |
-
// Get regular price: regular price doesn't include sales
|
153 |
-
$regular_price = floatval( $this->get_regular_price() );
|
154 |
-
|
155 |
-
// If it's a bookable product, the normal price is null/0.
|
156 |
-
if ( ! $regular_price && $this->is_bookable_product() ) {
|
157 |
-
|
158 |
-
$product = new WC_Product_Booking( $this->woo_product );
|
159 |
-
$regular_price = is_callable( [ $product, 'get_display_cost' ] ) ? $product->get_display_cost() : 0;
|
160 |
-
}
|
161 |
-
|
162 |
-
// Get regular price plus tax, if it's set to display and taxable
|
163 |
-
// whether price includes tax is based on 'woocommerce_tax_display_shop'
|
164 |
-
$price = $this->get_price_plus_tax( $regular_price );
|
165 |
-
$this->fb_price = intval( round( $price * 100 ) );
|
166 |
-
return $this->fb_price;
|
167 |
}
|
168 |
|
169 |
|
@@ -230,6 +192,24 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
230 |
return $image_urls;
|
231 |
}
|
232 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
233 |
// Returns the parent image id for variable products only.
|
234 |
public function get_parent_image_id() {
|
235 |
if ( WC_Facebookcommerce_Utils::is_variation_type( $this->woo_product->get_type() ) ) {
|
@@ -385,29 +365,16 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
385 |
/**
|
386 |
* Determines whether a product should be excluded from all-products sync or the feed file.
|
387 |
*
|
388 |
-
* The plugin also avoids trying to get the Facebook ID of products where is_hidden() returns true.
|
389 |
-
*
|
390 |
* @see SkyVerge\WooCommerce\Facebook\Products\Sync::create_or_update_all_products()
|
391 |
* @see WC_Facebook_Product_Feed::write_product_feed_file()
|
392 |
-
*
|
|
|
393 |
*/
|
394 |
public function is_hidden() {
|
395 |
-
$wpid = $this->id;
|
396 |
-
if ( WC_Facebookcommerce_Utils::is_variation_type( $this->get_type() ) ) {
|
397 |
-
$wpid = $this->get_parent_id();
|
398 |
-
}
|
399 |
-
$hidden_from_catalog = has_term(
|
400 |
-
'exclude-from-catalog',
|
401 |
-
'product_visibility',
|
402 |
-
$wpid
|
403 |
-
);
|
404 |
-
$hidden_from_search = has_term(
|
405 |
-
'exclude-from-search',
|
406 |
-
'product_visibility',
|
407 |
-
$wpid
|
408 |
-
);
|
409 |
|
410 |
-
|
|
|
|
|
411 |
}
|
412 |
|
413 |
|
@@ -574,18 +541,15 @@ if ( ! class_exists( 'WC_Facebook_Product' ) ) :
|
|
574 |
),
|
575 |
'description' => $this->get_fb_description(),
|
576 |
'image_url' => $image_urls[0], // The array can't be empty.
|
577 |
-
'additional_image_urls' =>
|
578 |
'url' => $product_url,
|
579 |
'category' => $categories['categories'],
|
580 |
'brand' => Framework\SV_WC_Helper::str_truncate( $brand, 100 ),
|
581 |
'retailer_id' => $retailer_id,
|
582 |
'price' => $this->get_fb_price(),
|
583 |
'currency' => get_woocommerce_currency(),
|
584 |
-
'availability' => $this->is_in_stock() ? 'in stock' :
|
585 |
-
'
|
586 |
-
'visibility' => ! $this->is_hidden()
|
587 |
-
? \WC_Facebookcommerce_Integration::FB_SHOP_PRODUCT_VISIBLE
|
588 |
-
: \WC_Facebookcommerce_Integration::FB_SHOP_PRODUCT_HIDDEN,
|
589 |
);
|
590 |
|
591 |
// Only use checkout URLs if they exist.
|
124 |
}
|
125 |
|
126 |
public function get_fb_price() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
127 |
|
128 |
+
return Products::get_product_price( $this->woo_product );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
}
|
130 |
|
131 |
|
192 |
return $image_urls;
|
193 |
}
|
194 |
|
195 |
+
|
196 |
+
/**
|
197 |
+
* Gets the list of additional image URLs for the product from the complete list of image URLs.
|
198 |
+
*
|
199 |
+
* It assumes the first URL will be used as the product image.
|
200 |
+
* It returns 20 or less image URLs because Facebook doesn't allow more items on the additional_image_urls field.
|
201 |
+
*
|
202 |
+
* @since 2.0.2
|
203 |
+
*
|
204 |
+
* @param array $image_urls all image URLs for the product
|
205 |
+
* @return array
|
206 |
+
*/
|
207 |
+
private function get_additional_image_urls( $image_urls ) {
|
208 |
+
|
209 |
+
return array_slice( $image_urls, 1, 20 );
|
210 |
+
}
|
211 |
+
|
212 |
+
|
213 |
// Returns the parent image id for variable products only.
|
214 |
public function get_parent_image_id() {
|
215 |
if ( WC_Facebookcommerce_Utils::is_variation_type( $this->woo_product->get_type() ) ) {
|
365 |
/**
|
366 |
* Determines whether a product should be excluded from all-products sync or the feed file.
|
367 |
*
|
|
|
|
|
368 |
* @see SkyVerge\WooCommerce\Facebook\Products\Sync::create_or_update_all_products()
|
369 |
* @see WC_Facebook_Product_Feed::write_product_feed_file()
|
370 |
+
*
|
371 |
+
* @deprecated 2.0.2
|
372 |
*/
|
373 |
public function is_hidden() {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
374 |
|
375 |
+
wc_deprecated_function( __METHOD__, '2.0.2', 'Products::product_should_be_synced()' );
|
376 |
+
|
377 |
+
return $this->woo_product instanceof \WC_Product && ! Products::product_should_be_synced( $this->woo_product );
|
378 |
}
|
379 |
|
380 |
|
541 |
),
|
542 |
'description' => $this->get_fb_description(),
|
543 |
'image_url' => $image_urls[0], // The array can't be empty.
|
544 |
+
'additional_image_urls' => $this->get_additional_image_urls( $image_urls ),
|
545 |
'url' => $product_url,
|
546 |
'category' => $categories['categories'],
|
547 |
'brand' => Framework\SV_WC_Helper::str_truncate( $brand, 100 ),
|
548 |
'retailer_id' => $retailer_id,
|
549 |
'price' => $this->get_fb_price(),
|
550 |
'currency' => get_woocommerce_currency(),
|
551 |
+
'availability' => $this->is_in_stock() ? 'in stock' : 'out of stock',
|
552 |
+
'visibility' => Products::is_product_visible( $this->woo_product ) ? \WC_Facebookcommerce_Integration::FB_SHOP_PRODUCT_VISIBLE : \WC_Facebookcommerce_Integration::FB_SHOP_PRODUCT_HIDDEN,
|
|
|
|
|
|
|
553 |
);
|
554 |
|
555 |
// Only use checkout URLs if they exist.
|
includes/fbproductfeed.php
CHANGED
@@ -12,6 +12,7 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|
12 |
exit;
|
13 |
}
|
14 |
|
|
|
15 |
use SkyVerge\WooCommerce\Facebook\Products\Feed;
|
16 |
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
17 |
|
@@ -565,16 +566,13 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
565 |
|
566 |
$woo_product = new WC_Facebook_Product( $wp_id );
|
567 |
|
568 |
-
if
|
569 |
-
|
570 |
-
}
|
571 |
-
|
572 |
-
if ( get_option( 'woocommerce_hide_out_of_stock_items' ) === 'yes' && ! $woo_product->is_in_stock() ) {
|
573 |
continue;
|
574 |
}
|
575 |
|
576 |
// skip if not enabled for sync
|
577 |
-
if (
|
578 |
continue;
|
579 |
}
|
580 |
|
@@ -737,6 +735,11 @@ if ( ! class_exists( 'WC_Facebook_Product_Feed' ) ) :
|
|
737 |
$product_data['default_product'] = '';
|
738 |
}
|
739 |
|
|
|
|
|
|
|
|
|
|
|
740 |
return $product_data['retailer_id'] . ',' .
|
741 |
static::format_string_for_feed( $product_data['name'] ) . ',' .
|
742 |
static::format_string_for_feed( $product_data['description'] ) . ',' .
|
12 |
exit;
|
13 |
}
|
14 |
|
15 |
+
use SkyVerge\WooCommerce\Facebook\Products;
|
16 |
use SkyVerge\WooCommerce\Facebook\Products\Feed;
|
17 |
use SkyVerge\WooCommerce\PluginFramework\v5_5_4 as Framework;
|
18 |
|
566 |
|
567 |
$woo_product = new WC_Facebook_Product( $wp_id );
|
568 |
|
569 |
+
// skip if we don't have a valid product object
|
570 |
+
if ( ! $woo_product->woo_product instanceof \WC_Product ) {
|
|
|
|
|
|
|
571 |
continue;
|
572 |
}
|
573 |
|
574 |
// skip if not enabled for sync
|
575 |
+
if ( ! Products::product_should_be_synced( $woo_product->woo_product ) ) {
|
576 |
continue;
|
577 |
}
|
578 |
|
735 |
$product_data['default_product'] = '';
|
736 |
}
|
737 |
|
738 |
+
// when dealing with the feed file, only set out-of-stock products as hidden
|
739 |
+
if ( Products::product_should_be_deleted( $woo_product->woo_product ) ) {
|
740 |
+
$product_data['visibility'] = \WC_Facebookcommerce_Integration::FB_SHOP_PRODUCT_HIDDEN;
|
741 |
+
}
|
742 |
+
|
743 |
return $product_data['retailer_id'] . ',' .
|
744 |
static::format_string_for_feed( $product_data['name'] ) . ',' .
|
745 |
static::format_string_for_feed( $product_data['description'] ) . ',' .
|
readme.txt
CHANGED
@@ -3,7 +3,7 @@ Contributors: facebook, automattic, woothemes
|
|
3 |
Tags: facebook, shop, catalog, advertise, pixel, product
|
4 |
Requires at least: 4.4
|
5 |
Tested up to: 5.3.2
|
6 |
-
Stable tag: 2.0.
|
7 |
Requires PHP: 5.6 or greater
|
8 |
MySQL: 5.6 or greater
|
9 |
License: GPLv2 or later
|
@@ -39,6 +39,13 @@ When opening a bug on GitHub, please give us as many details as possible.
|
|
39 |
|
40 |
== Changelog ==
|
41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
= 2020.08.17 - version 2.0.1 =
|
43 |
* Fix - Ensure the configured business name is never empty when connecting to Facebook
|
44 |
|
3 |
Tags: facebook, shop, catalog, advertise, pixel, product
|
4 |
Requires at least: 4.4
|
5 |
Tested up to: 5.3.2
|
6 |
+
Stable tag: 2.0.2
|
7 |
Requires PHP: 5.6 or greater
|
8 |
MySQL: 5.6 or greater
|
9 |
License: GPLv2 or later
|
39 |
|
40 |
== Changelog ==
|
41 |
|
42 |
+
= 2020.09.25 - version 2.0.2 =
|
43 |
+
* Tweak - Allow simple and variable products with zero/empty price to sync to Facebook
|
44 |
+
* Tweak - Use the bundle price for Product Bundles products with individually priced items
|
45 |
+
* Fix - Update connection parameters to use an array to pass the Messenger domain
|
46 |
+
* Fix - Ensure out-of-stock products are marked as such in Facebook when the feed file replacement is run
|
47 |
+
* Fix - Address a potential error when connecting from a site whose title contains special characters
|
48 |
+
|
49 |
= 2020.08.17 - version 2.0.1 =
|
50 |
* Fix - Ensure the configured business name is never empty when connecting to Facebook
|
51 |
|