Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 111 additions & 0 deletions assets/css/admin/facebook-for-woocommerce-products-admin.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
border-bottom: 1px solid #eee;
}

#facebook_options .google_product_catgory {
border-top: 1px solid #eee;
}

.woocommerce_variable_attributes .wp-editor-wrap label {
float: left;
Expand Down Expand Up @@ -165,4 +168,112 @@
.wp-editor-wrap {
width: 100%;
max-width: 100%;
}

.facebook-metabox {
overflow: hidden;
clear: both;
border: 1px solid #ddd;
margin: 16px 0 !important;
background: #fff;
padding: 0 !important; /* Remove the previous padding */
border-bottom: 1px solid #eee !important;
}
.facebook-metabox h3 {
margin: 0 !important;
font-size: 1em !important;
padding: 0.5em 0.75em 0.5em 1em !important;
cursor: pointer;
border-bottom: 1px solid #ddd;
}
.facebook-metabox.closed .handlediv:before {
content: "\f140" !important;
}
.facebook-metabox .handlediv:before {
content: "\f142" !important;
font: normal 20px/1 dashicons;
}
.facebook-metabox .wc-metabox-content {
padding: 1em;
background: #fff;
}
.facebook-metabox h3 strong {
line-height: 26px;
font-weight: 600;
}

.sync-indicator .sync-tooltip {
display: none;
position: absolute;
background: #32373c;
padding: 8px;
border-radius: 3px;
color: #fff;
font-size: 11px;
font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen-Sans,Ubuntu,Cantarell,"Helvetica Neue",sans-serif;
line-height: 1.4;
white-space: nowrap;
z-index: 9999;
top: 100%;
left: 50%;
transform: translateX(-50%) translateY(8px);
}

.sync-indicator .sync-tooltip:before {
content: '';
position: absolute;
border: 6px solid transparent;
border-bottom-color: #32373c;
top: -12px;
left: 50%;
transform: translateX(-50%);
}

.sync-indicator:hover .sync-tooltip {
display: block;
}

.synced-attribute {
background-color: #f0f0f1 !important;
cursor: not-allowed;
}

.sync-indicator .sync-tooltip:before {
content: '';
position: absolute;
border: 6px solid transparent;
border-bottom-color: #32373c;
top: -12px;
left: 50%;
transform: translateX(-50%);
}

.sync-indicator:hover .sync-tooltip {
display: block;
}

.wc-attributes-icon {
display: inline-block;
margin-left: 8px;
cursor: help;
vertical-align: middle;
font-size: 14px;
position: relative;
line-height: 1;
top: 2px;
}

.wc-attributes-icon:before {
font-family: Dashicons;
content: "\f175";
}

.woocommerce_options_panel {
input[type="text"],
input[type="number"],
input[type="email"],
input[type="url"],
select {
font-size: 12px !important;
}
}
7 changes: 7 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
*** Facebook for WooCommerce Changelog ***

= 3.4.5 - 2025-04-01 =
* Tweak - Add new product field external_update_time to measure product update latency by @mshymon in #2973
* Fix - for 'PHP Warning: Undefined variable $fb_product_parent' by @mshymon in #2976
* Fix - Updated logic to choose/create the feed for product sync by @mshymon in #2989
* Add - Facebook Product Data Tab Enhancement by @devbodaghe in #2938
* Fix - PHP Warning for empty attributes by @vinkmeta in #3001

= 3.4.4 - 2025-03-26 =
* Add - Create tests for ProductFeedUploads create endpoint by @ajello-meta in #2902
* Add - Create tests for ProductFeedUploads read endpoint by @ajello-meta in #2903
Expand Down
155 changes: 99 additions & 56 deletions facebook-commerce.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ class WC_Facebookcommerce_Integration extends WC_Integration {


// TODO probably some of these meta keys need to be moved to Facebook\Products {FN 2020-01-13}.
public const FB_PRODUCT_GROUP_ID = 'fb_product_group_id';
public const FB_PRODUCT_ITEM_ID = 'fb_product_item_id';
public const FB_PRODUCT_DESCRIPTION = 'fb_product_description';
public const FB_PRODUCT_GROUP_ID = 'fb_product_group_id';
public const FB_PRODUCT_ITEM_ID = 'fb_product_item_id';
public const FB_PRODUCT_DESCRIPTION = 'fb_product_description';
public const FB_RICH_TEXT_DESCRIPTION = 'fb_rich_text_description';
/** @var string the API flag to set a product as visible in the Facebook shop */
public const FB_SHOP_PRODUCT_VISIBLE = 'published';
Expand Down Expand Up @@ -715,7 +715,7 @@ public function load_assets() {
},
feed: {
totalVisibleProducts: '<?php echo esc_js( $this->get_product_count() ); ?>',
hasClientSideFeedUpload: '<?php echo esc_js( ! ! $this->get_feed_id() ); ?>',
hasClientSideFeedUpload: '<?php echo esc_js( (bool) $this->get_feed_id() ); ?>',
enabled: true,
format: 'csv'
},
Expand Down Expand Up @@ -805,20 +805,18 @@ public function on_product_save( int $wp_id ) {
}
$this->delete_fb_product( $delete_product );
}
} else {
if ( $sync_enabled ) {
} elseif ( $sync_enabled ) {
Products::enable_sync_for_products( [ $product ] );
Products::set_product_visibility( $product, Admin::SYNC_MODE_SYNC_AND_HIDE !== $sync_mode );
$this->save_product_settings( $product );
} else {
// if previously enabled, add a notice on the next page load
if ( Products::is_sync_enabled_for_product( $product ) ) {
Admin::add_product_disabled_sync_notice();
}
Products::disable_sync_for_products( [ $product ] );
if ( in_array( $wp_id, $products_to_delete_from_facebook, true ) ) {
$this->delete_fb_product( $product );
}
} else {
// if previously enabled, add a notice on the next page load
if ( Products::is_sync_enabled_for_product( $product ) ) {
Admin::add_product_disabled_sync_notice();
}
Products::disable_sync_for_products( [ $product ] );
if ( in_array( $wp_id, $products_to_delete_from_facebook, true ) ) {
$this->delete_fb_product( $product );
}
}
if ( $sync_enabled ) {
Expand All @@ -843,16 +841,58 @@ public function on_product_save( int $wp_id ) {
}

/**
* Saves the submitted Facebook settings for a variable product.
*
*
* @param \WC_Product $product The variable product object.
*/
private function save_variable_product_settings( WC_Product $product ) {
$woo_product = new WC_Facebook_Product( $product->get_id() );
if ( isset( $_POST[ WC_Facebook_Product::FB_VARIABLE_BRAND ] ) ) {
$woo_product->set_fb_brand( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_VARIABLE_BRAND ] ) ) );
* Saves Facebook product attributes from POST data.
*
* @param WC_Facebook_Product $woo_product The Facebook product object
*/
private function save_facebook_product_attributes( $woo_product ) {
// phpcs:disable WordPress.Security.NonceVerification.Missing
if ( isset( $_POST[ WC_Facebook_Product::FB_BRAND ] ) ) {
$woo_product->set_fb_brand( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_BRAND ] ) ) );
}

if ( isset( $_POST[ WC_Facebook_Product::FB_MPN ] ) ) {
$woo_product->set_fb_mpn( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_MPN ] ) ) );
}

if ( isset( $_POST[ WC_Facebook_Product::FB_SIZE ] ) ) {
$woo_product->set_fb_size( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_SIZE ] ) ) );
}

if ( isset( $_POST[ WC_Facebook_Product::FB_COLOR ] ) ) {
$woo_product->set_fb_color( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_COLOR ] ) ) );
}

if ( isset( $_POST[ WC_Facebook_Product::FB_MATERIAL ] ) ) {
$woo_product->set_fb_material( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_MATERIAL ] ) ) );
}

if ( isset( $_POST[ WC_Facebook_Product::FB_PATTERN ] ) ) {
$woo_product->set_fb_pattern( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_PATTERN ] ) ) );
}

if ( isset( $_POST[ WC_Facebook_Product::FB_AGE_GROUP ] ) ) {
$woo_product->set_fb_age_group( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_AGE_GROUP ] ) ) );
}

if ( isset( $_POST[ WC_Facebook_Product::FB_GENDER ] ) ) {
$woo_product->set_fb_gender( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_GENDER ] ) ) );
}

if ( isset( $_POST[ WC_Facebook_Product::FB_PRODUCT_CONDITION ] ) ) {
$woo_product->set_fb_condition( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_PRODUCT_CONDITION ] ) ) );
}
// phpcs:enable WordPress.Security.NonceVerification.Missing
}

/**
* Saves the submitted Facebook settings for a variable product.
*
* @param \WC_Product $product The variable product object.
*/
private function save_variable_product_settings( $product ) {
$woo_product = new WC_Facebook_Product( $product->get_id() );
$this->save_facebook_product_attributes( $woo_product );
}

/**
Expand Down Expand Up @@ -889,14 +929,7 @@ private function save_product_settings( WC_Product $product ) {
$woo_product->set_product_video_urls( $attachment_ids );
}

if ( isset( $_POST[ WC_Facebook_Product::FB_BRAND ] ) ) {
$woo_product->set_fb_brand( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_BRAND ] ) ) );
}

if ( isset( $_POST[ WC_Facebook_Product::FB_MPN ] ) ) {
$woo_product->set_fb_mpn( sanitize_text_field( wp_unslash( $_POST[ WC_Facebook_Product::FB_MPN ] ) ) );
}
// phpcs:enable WordPress.Security.NonceVerification.Missing
$this->save_facebook_product_attributes( $woo_product );
}

/**
Expand All @@ -921,7 +954,7 @@ public function on_product_delete( int $product_id ) {
*/
// phpcs:ignore WordPress.Security.NonceVerification.Missing
if ( ( ! wp_doing_ajax() || ! isset( $_POST['action'] ) || 'ajax_delete_fb_product' !== $_POST['action'] )
&& ! Products::published_product_should_be_synced( $product ) && ! $product->is_type( 'variable' ) ) {
&& ! Products::published_product_should_be_synced( $product ) && ! $product->is_type( 'variable' ) ) {
return;
}

Expand Down Expand Up @@ -1070,8 +1103,7 @@ public function delete_draft_product( $post ) {
return;
}

$this->on_product_delete ( $post->ID );

$this->on_product_delete( $post->ID );
}


Expand Down Expand Up @@ -1629,7 +1661,7 @@ public function delete_product_set_item( string $fb_product_set_id ) {
* - product_item_id : if exists, means product was created else not and don't display
* - should_sync: Don't display if the product is not supposed to be synced.
*
* @param WP_Post $post Wordpress Post
* @param WP_Post $post WordPress Post
* @return void
*/
public function display_batch_api_completed( $post ) {
Expand Down Expand Up @@ -2223,7 +2255,7 @@ private function sync_facebook_products_using_background_processor() {
);

$this->on_product_publish( $post_id );
$count++;
++$count;
}
WC_Facebookcommerce_Utils::log( 'Synced ' . $count . ' products' );
$this->remove_sticky_message();
Expand Down Expand Up @@ -2647,24 +2679,35 @@ public function is_product_sync_enabled() {
}

/**
* Return true if (legacy) feed generation is enabled.
*
* Feed generation for product sync is enabled by default, and generally recommended.
* Large stores, or stores running on shared hosting (low resources) may have issues
* with feed generation. This option allows those stores to disable generation to
* work around the issue.
*
* Note - this is temporary. In a future release, an improved feed system will be
* implemented, which should work well for all stores. This option will not disable
* the new improved implementation.
*
* @since 2.5.0
*
* @return bool
*/
public function is_legacy_feed_file_generation_enabled() {
return 'yes' === get_option( self::OPTION_LEGACY_FEED_FILE_GENERATION_ENABLED, 'yes' );
}
* Return true if (legacy) feed generation is enabled.
*
* Feed generation for product sync is enabled by default, and generally recommended.
* Large stores, or stores running on shared hosting (low resources) may have issues
* with feed generation. This option allows those stores to disable generation to
* work around the issue.
*
* Note - this is temporary. In a future release, an improved feed system will be
* implemented, which should work well for all stores. This option will not disable
* the new improved implementation.
*
* @since 2.5.0
*
* @return bool
*/
public function is_legacy_feed_file_generation_enabled() {
return 'yes' === get_option( self::OPTION_LEGACY_FEED_FILE_GENERATION_ENABLED, 'yes' );
}

/**
* Determines whether meta diagnosis is enabled.
*
* @return bool
* @since 3.4.4
*
*/
public function is_meta_diagnosis_enabled() {
return (bool) ( 'yes' === get_option( self::SETTING_ENABLE_META_DIAGNOSIS ) );
}

/**
* Determines whether debug mode is enabled.
Expand Down Expand Up @@ -2900,7 +2943,7 @@ public function update_fb_visibility( $product_id, $visibility ) {
$fb_product_item_id = $this->get_product_fbid( self::FB_PRODUCT_ITEM_ID, $product->get_id() );
if ( ! $fb_product_item_id ) {
\WC_Facebookcommerce_Utils::fblog( $fb_product_item_id . " doesn't exist but underwent a visibility transform.", [], true );
return;
return;
}
try {
$set_visibility = $this->facebook_for_woocommerce->get_api()->update_product_item( $fb_product_item_id, [ 'visibility' => $visibility ] );
Expand Down
4 changes: 2 additions & 2 deletions facebook-for-woocommerce.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* 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.
* Author: Facebook
* Author URI: https://www.facebook.com/
* Version: 3.4.4
* Version: 3.4.5
* Requires at least: 5.6
* Requires PHP: 7.4
* Text Domain: facebook-for-woocommerce
Expand Down Expand Up @@ -48,7 +48,7 @@ class WC_Facebook_Loader {
/**
* @var string the plugin version. This must be in the main plugin file to be automatically bumped by Woorelease.
*/
const PLUGIN_VERSION = '3.4.4'; // WRCS: DEFINED_VERSION.
const PLUGIN_VERSION = '3.4.5'; // WRCS: DEFINED_VERSION.

// Minimum PHP version required by this plugin.
const MINIMUM_PHP_VERSION = '7.4.0';
Expand Down
Loading