diff --git a/assets/js/admin/enhanced-settings-sync.js b/assets/js/admin/enhanced-settings-sync.js new file mode 100644 index 000000000..56adb5332 --- /dev/null +++ b/assets/js/admin/enhanced-settings-sync.js @@ -0,0 +1,76 @@ +/** + * 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 + */ + +jQuery(document).ready(function($) { + /** + * Handle the sync products button click event + * + * @since 3.5.0 + * + * @param {object} event + */ + $('#wc-facebook-enhanced-settings-sync-products').click(function(event) { + event.preventDefault(); + var button = $(this); + + button.html('Syncing...'); + button.prop('disabled', true); + + var data = { + action: "wc_facebook_sync_products", + nonce: wc_facebook_enhanced_settings_sync.sync_products_nonce + }; + + $.post(wc_facebook_enhanced_settings_sync.ajax_url, data, function(response) { + if (response.success) { + button.html('Sync completed'); + button.prop('disabled', false); + } else { + button.html('Sync failed'); + button.prop('disabled', false); + } + }).fail(function() { + button.html('Sync failed'); + button.prop('disabled', false); + }); + }); + + /** + * Handle the sync coupons button click event + * + * @since 3.5.0 + * + * @param {object} event + */ + $('#wc-facebook-enhanced-settings-sync-coupons').click(function(event) { + event.preventDefault(); + var button = $(this); + + button.html('Syncing...'); + button.prop('disabled', true); + + var data = { + action: "wc_facebook_sync_coupons", + nonce: wc_facebook_enhanced_settings_sync.sync_coupons_nonce + }; + + $.post(wc_facebook_enhanced_settings_sync.ajax_url, data, function(response) { + if (response.success) { + button.html('Sync completed'); + button.prop('disabled', false); + } else { + button.html('Sync failed'); + button.prop('disabled', false); + } + }).fail(function() { + button.html('Sync failed'); + button.prop('disabled', false); + }); + }); +}); diff --git a/includes/AJAX.php b/includes/AJAX.php index b92243f1d..74c82cf5c 100644 --- a/includes/AJAX.php +++ b/includes/AJAX.php @@ -1,5 +1,4 @@ get_products_sync_handler()->create_or_update_all_products(); + try { + facebook_for_woocommerce()->get_products_sync_handler()->create_or_update_all_products(); + wp_send_json_success(); + } catch ( \Exception $exception ) { + wp_send_json_error( $exception->getMessage() ); + } + } - wp_send_json_success(); + /** + * Syncs all coupons via AJAX. + * + * @internal + * + * @since 3.5.0 + */ + public function sync_coupons() { + check_admin_referer( Shops::ACTION_SYNC_COUPONS, 'nonce' ); + + try { + facebook_for_woocommerce()->feed_manager->get_feed_instance( 'promotions' )->regenerate_feed(); + wp_send_json_success(); + } catch ( \Exception $exception ) { + wp_send_json_error( $exception->getMessage() ); + } } @@ -130,7 +144,6 @@ public function sync_products() { * @since 2.0.0 */ public function get_sync_status() { - check_admin_referer( Product_Sync::ACTION_GET_SYNC_STATUS, 'nonce' ); $remaining_products = 0; @@ -142,7 +155,6 @@ public function get_sync_status() { ); if ( ! empty( $jobs ) ) { - // there should only be one processing job at a time, pluck the latest to convey status $job = $jobs[0]; @@ -165,7 +177,6 @@ public function get_sync_status() { * @since 1.10.0 */ public function handle_set_product_sync_bulk_action_prompt() { - check_ajax_referer( 'set-product-sync-bulk-action-prompt', 'security' ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended @@ -188,7 +199,6 @@ public function handle_set_product_sync_bulk_action_prompt() { // show modal if there's at least one product that belongs to an excluded term if ( $has_excluded_term ) { - ob_start(); ?> @@ -227,7 +237,6 @@ class="button button-large button-primary" * @since 1.10.0 */ public function handle_set_excluded_terms_prompt() { - check_ajax_referer( 'set-excluded-terms-prompt', 'security' ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized @@ -250,9 +259,7 @@ public function handle_set_excluded_terms_prompt() { } } - // query for products with sync enabled, belonging to the added term IDs and not belonging to the term IDs that are already stored in the setting $products = $this->get_products_to_be_excluded( $new_category_ids, $new_tag_ids ); - if ( ! empty( $products ) ) { ob_start(); @@ -275,7 +282,7 @@ class="button button-large button-primary" wp_send_json_error( array( 'message' => sprintf( - /* translators: Placeholder %s -
tags */ + /* translators: Placeholder %s -
tags */ __( 'The categories and/or tags that you have selected to exclude from sync contain products that are currently synced to Facebook.%sTo exclude these products from the Facebook sync, click Exclude Products. To review the category / tag exclusion settings, click Cancel.', 'facebook-for-woocommerce' ), '

' ), @@ -304,8 +311,6 @@ class="button button-large button-primary" * @return int[] */ private function get_products_to_be_excluded( $new_excluded_categories = array(), $new_excluded_tags = array() ) { - - // products with sync enabled $sync_enabled_meta_query = array( 'relation' => 'OR', array( @@ -325,20 +330,15 @@ private function get_products_to_be_excluded( $new_excluded_categories = array() ); if ( ! empty( $new_excluded_categories ) ) { - - // products that belong to the new excluded categories $categories_tax_query = array( 'taxonomy' => 'product_cat', 'terms' => $new_excluded_categories, ); - if ( $integration = facebook_for_woocommerce()->get_integration() ) { - - // products that do not belong to the saved excluded categories + $integration = facebook_for_woocommerce()->get_integration(); + if ( $integration ) { $saved_excluded_categories = $integration->get_excluded_product_category_ids(); - if ( ! empty( $saved_excluded_categories ) ) { - $categories_tax_query = array( 'relation' => 'AND', $categories_tax_query, @@ -355,20 +355,15 @@ private function get_products_to_be_excluded( $new_excluded_categories = array() } if ( ! empty( $new_excluded_tags ) ) { - - // products that belong to the new excluded tags $tags_tax_query = array( 'taxonomy' => 'product_tag', 'terms' => $new_excluded_tags, ); - if ( $integration = facebook_for_woocommerce()->get_integration() ) { - + $integration = facebook_for_woocommerce()->get_integration(); + if ( $integration ) { $save_excluded_tags = $integration->get_excluded_product_tag_ids(); - if ( ! empty( $save_excluded_tags ) ) { - - // products that do not belong to the saved excluded tags $tags_tax_query = array( 'relation' => 'AND', $tags_tax_query, @@ -382,11 +377,8 @@ private function get_products_to_be_excluded( $new_excluded_categories = array() } if ( empty( $products_query_vars['tax_query'] ) ) { - $products_query_vars['tax_query'] = $tags_tax_query; - } else { - $products_query_vars['tax_query'] = array( 'relation' => 'OR', $products_query_vars, @@ -399,6 +391,4 @@ private function get_products_to_be_excluded( $new_excluded_categories = array() return $products_query->posts; } - - } diff --git a/includes/Admin/Settings_Screens/Shops.php b/includes/Admin/Settings_Screens/Shops.php index 830e0ab48..f7a118d19 100644 --- a/includes/Admin/Settings_Screens/Shops.php +++ b/includes/Admin/Settings_Screens/Shops.php @@ -25,6 +25,12 @@ class Shops extends Abstract_Settings_Screen { /** @var string */ const ID = 'shops'; + /** @var string */ + const ACTION_SYNC_PRODUCTS = 'wc_facebook_sync_products'; + + /** @var string */ + const ACTION_SYNC_COUPONS = 'wc_facebook_sync_coupons'; + /** * Shops constructor. * @@ -107,6 +113,24 @@ public function enqueue_assets() { } wp_enqueue_style( 'wc-facebook-admin-connection-settings', facebook_for_woocommerce()->get_plugin_url() . '/assets/css/admin/facebook-for-woocommerce-connection.css', array(), \WC_Facebookcommerce::VERSION ); + + wp_enqueue_script( + 'wc-facebook-enhanced-settings-sync', + facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/enhanced-settings-sync.js', + array( 'jquery' ), + \WC_Facebookcommerce::PLUGIN_VERSION, + true + ); + + wp_localize_script( + 'wc-facebook-enhanced-settings-sync', + 'wc_facebook_enhanced_settings_sync', + array( + 'ajax_url' => admin_url( 'admin-ajax.php' ), + 'sync_products_nonce' => wp_create_nonce( self::ACTION_SYNC_PRODUCTS ), + 'sync_coupons_nonce' => wp_create_nonce( self::ACTION_SYNC_COUPONS ), + ) + ); } /** @@ -115,7 +139,13 @@ public function enqueue_assets() { * @since 3.5.0 */ public function render() { + $is_connected = facebook_for_woocommerce()->get_connection_handler()->is_connected(); + $this->render_facebook_iframe(); + + if ( $is_connected ) { + $this->render_troubleshooting_button_and_drawer(); + } } /** @@ -147,17 +177,18 @@ private function render_facebook_iframe() { ?>
+ id="facebook-commerce-iframe-enhanced" + src="" + >
render_troubleshooting_button_and_drawer(); - } } + /** + * Renders the troubleshooting button and drawer. + * + * @since 3.5.0 + */ private function render_troubleshooting_button_and_drawer() { ?> @@ -171,6 +202,42 @@ private function render_troubleshooting_button_and_drawer() { @@ -199,7 +266,7 @@ private function render_troubleshooting_button_and_drawer() { justify-content: space-between; align-items: center; margin-bottom: 20px; - box-sizing: border-box; + box-sizing: border-box; } .drawer-toggle-button:hover { @@ -220,22 +287,34 @@ private function render_troubleshooting_button_and_drawer() { max-width: 1100px; background-color: #fff; border-bottom: 1px solid #ccc; - border-right: 1px solid #ccc; - border-left: 1px solid #ccc; + border-right: 1px solid #ccc; + border-left: 1px solid #ccc; overflow: hidden; transition: max-height 0.3s ease, margin-bottom 0.3s ease; max-height: 0; margin: 0 auto; - box-sizing: border-box; + box-sizing: border-box; } .settings-drawer-content { padding: 20px; padding-bottom: 0; } + + .button:disabled { + background-color: #f1f1f1; + cursor: not-allowed; + } + + .sync-description { + font-size: 12px; + color: #666; + padding-top: 8px; + }