diff --git a/includes/Admin.php b/includes/Admin.php index 141110acd..71a292c78 100644 --- a/includes/Admin.php +++ b/includes/Admin.php @@ -1,5 +1,4 @@ get_asset_build_dir_url() . '/admin/modal.js', array( 'jquery', 'wc-backbone-modal', 'jquery-blockui' ), - \WC_Facebookcommerce::PLUGIN_VERSION + \WC_Facebookcommerce::PLUGIN_VERSION, + false ); // enqueue google product category select @@ -171,7 +171,8 @@ public function enqueue_scripts() { 'wc-facebook-google-product-category-fields', facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/google-product-category-fields.js', array( 'jquery' ), - \WC_Facebookcommerce::PLUGIN_VERSION + \WC_Facebookcommerce::PLUGIN_VERSION, + false ); wp_localize_script( @@ -232,7 +233,8 @@ public function enqueue_scripts() { 'facebook-for-woocommerce-products-admin', facebook_for_woocommerce()->get_asset_build_dir_url() . '/admin/products-admin.js', [ 'jquery', 'wc-backbone-modal', 'jquery-blockui', 'facebook-for-woocommerce-modal' ], - \WC_Facebookcommerce::PLUGIN_VERSION + \WC_Facebookcommerce::PLUGIN_VERSION, + false ); wp_localize_script( 'facebook-for-woocommerce-products-admin', @@ -354,7 +356,7 @@ private function get_product_not_ready_modal_buttons() { + > + > + > + > -1, 'post_type' => 'product_variation', - 'meta_query' => array( + 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query 'key' => Products::VISIBILITY_META_KEY, 'value' => 'no', ), @@ -639,7 +641,7 @@ public function filter_products_by_sync_enabled( $query_vars ) { 'fields' => 'ids', 'limit' => -1, 'post_type' => 'product', - 'meta_query' => array( + 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query array( 'key' => Products::SYNC_ENABLED_META_KEY, 'value' => 'no', @@ -654,7 +656,7 @@ public function filter_products_by_sync_enabled( $query_vars ) { array( 'limit' => -1, 'post_type' => 'product_variation', - 'meta_query' => array( + 'meta_query' => array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query array( 'key' => Products::SYNC_ENABLED_META_KEY, 'value' => 'no', @@ -683,7 +685,7 @@ public function filter_products_by_sync_enabled( $query_vars ) { // remove sync enabled and visibility meta queries if ( ! empty( $original_meta_query ) ) { - $query_vars['meta_query'] = $original_meta_query; + $query_vars['meta_query'] = $original_meta_query; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query } else { unset( $query_vars['meta_query'] ); } @@ -707,7 +709,7 @@ public function filter_products_by_sync_enabled( $query_vars ) { * @return array */ private function add_query_vars_to_find_products_with_sync_enabled( array $query_vars ) { - $meta_query = array( + $meta_query = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query 'relation' => 'OR', array( 'key' => Products::SYNC_ENABLED_META_KEY, @@ -720,10 +722,10 @@ private function add_query_vars_to_find_products_with_sync_enabled( array $query ); if ( empty( $query_vars['meta_query'] ) ) { - $query_vars['meta_query'] = $meta_query; + $query_vars['meta_query'] = $meta_query; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query } elseif ( is_array( $query_vars['meta_query'] ) ) { $original_meta_query = $query_vars['meta_query']; - $query_vars['meta_query'] = array( + $query_vars['meta_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query 'relation' => 'AND', $original_meta_query, $meta_query, @@ -773,7 +775,7 @@ private function maybe_add_tax_query_for_excluded_taxonomies( $query_vars, $in = } if ( $tax_query && empty( $query_vars['tax_query'] ) ) { - $query_vars['tax_query'] = $tax_query; + $query_vars['tax_query'] = $tax_query; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query } elseif ( $tax_query && is_array( $query_vars ) ) { $query_vars['tax_query'][] = $tax_query; } @@ -790,9 +792,10 @@ private function maybe_add_tax_query_for_excluded_taxonomies( $query_vars, $in = * * @param array $query_vars * @return array + * @todo Figure out if meta_query is slow and can be replaced with faster query */ private function add_query_vars_to_find_visible_products( array $query_vars ) { - $visibility_meta_query = array( + $visibility_meta_query = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query 'relation' => 'OR', array( 'key' => Products::VISIBILITY_META_KEY, @@ -805,10 +808,10 @@ private function add_query_vars_to_find_visible_products( array $query_vars ) { ); if ( empty( $query_vars['meta_query'] ) ) { - $query_vars['meta_query'] = $visibility_meta_query; + $query_vars['meta_query'] = $visibility_meta_query; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query } elseif ( is_array( $query_vars['meta_query'] ) ) { $enabled_meta_query = $query_vars['meta_query']; - $query_vars['meta_query'] = array( + $query_vars['meta_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query 'relation' => 'AND', $enabled_meta_query, $visibility_meta_query, @@ -828,16 +831,16 @@ private function add_query_vars_to_find_visible_products( array $query_vars ) { * @return array */ private function add_query_vars_to_find_hidden_products( array $query_vars ) { - $visibility_meta_query = array( + $visibility_meta_query = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query 'key' => Products::VISIBILITY_META_KEY, 'value' => 'no', ); if ( empty( $query_vars['meta_query'] ) ) { - $query_vars['meta_query'] = $visibility_meta_query; + $query_vars['meta_query'] = $visibility_meta_query; // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query } elseif ( is_array( $query_vars['meta_query'] ) ) { $enabled_meta_query = $query_vars['meta_query']; - $query_vars['meta_query'] = array( + $query_vars['meta_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query 'relation' => 'AND', $enabled_meta_query, $visibility_meta_query, @@ -897,7 +900,8 @@ public function handle_products_sync_bulk_actions( $redirect ) { /** @var \WC_Product_Variation[] $enabling_sync_virtual_variations virtual variations that are being included */ $enabling_sync_virtual_variations = []; foreach ( $product_ids as $product_id ) { - if ( $product = wc_get_product( $product_id ) ) { + $product = wc_get_product( $product_id ); + if ( $product ) { $products[] = $product; if ( 'facebook_include' === $action ) { if ( $product->is_virtual() && ! Products::is_sync_enabled_for_product( $product ) ) { @@ -961,7 +965,7 @@ public function handle_products_sync_bulk_actions( $redirect ) { * * @since 2.0.0 * - * @param \WC_Product $products + * @param \WC_Product[] $products Array of product objects to resync */ private function resync_products( array $products ) { @@ -1013,7 +1017,8 @@ public function maybe_show_product_disabled_sync_notice() { $transient_name = 'wc_' . facebook_for_woocommerce()->get_id() . '_show_product_disabled_sync_notice_' . get_current_user_id(); $message_id = 'wc-' . facebook_for_woocommerce()->get_id_dasherized() . '-product-disabled-sync'; - if ( ( $count = get_transient( $transient_name ) ) && ( Helper::is_current_screen( 'edit-product' ) || Helper::is_current_screen( 'product' ) ) ) { + $count = get_transient( $transient_name ); + if ( $count && ( Helper::is_current_screen( 'edit-product' ) || Helper::is_current_screen( 'product' ) ) ) { $message = sprintf( /* translators: Placeholders: %1$s - tag, %2$s - tag, %3$s - tag, %4$s - tag */ @@ -1053,7 +1058,8 @@ public function maybe_add_enabling_virtual_products_sync_notice() { $show_notice_transient_name = 'wc_' . facebook_for_woocommerce()->get_id() . '_enabling_virtual_products_sync_show_notice_' . get_current_user_id(); $affected_products_transient_name = 'wc_' . facebook_for_woocommerce()->get_id() . '_enabling_virtual_products_sync_affected_products_' . get_current_user_id(); - if ( Helper::is_current_screen( 'edit-product' ) && get_transient( $show_notice_transient_name ) && ( $affected_products = get_transient( $affected_products_transient_name ) ) ) { + $affected_products = get_transient( $affected_products_transient_name ); + if ( Helper::is_current_screen( 'edit-product' ) && get_transient( $show_notice_transient_name ) && $affected_products ) { $message = sprintf( esc_html( @@ -1100,10 +1106,13 @@ public function filter_virtual_products_affected_enabling_sync( $query_vars ) { $transient_name = 'wc_' . facebook_for_woocommerce()->get_id() . '_enabling_virtual_products_sync_affected_products_' . get_current_user_id(); - if ( isset( $_GET['facebook_show_affected_products'] ) && Helper::is_current_screen( 'edit-product' ) && $affected_products = get_transient( $transient_name ) ) { + $affected_products = get_transient( $transient_name ); + // phpcs:disable WordPress.Security.NonceVerification.Recommended + if ( isset( $_GET['facebook_show_affected_products'] ) && Helper::is_current_screen( 'edit-product' ) && $affected_products ) { $query_vars['post__in'] = $affected_products; } + // phpcs:enable WordPress.Security.NonceVerification.Recommended return $query_vars; } @@ -1196,8 +1205,8 @@ private function render_facebook_product_video_field( $video_urls ) { ?>

- - + +

ID, Products::SYNC_ENABLED_META_KEY, true ); - $is_visible = ( $visibility = get_post_meta( $post->ID, Products::VISIBILITY_META_KEY, true ) ) ? wc_string_to_bool( $visibility ) : true; + $visibility = get_post_meta( $post->ID, Products::VISIBILITY_META_KEY, true ); + $is_visible = $visibility ? wc_string_to_bool( $visibility ) : true; $product = wc_get_product( $post ); $fb_product_description = get_post_meta( $post->ID, \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION, true ); @@ -1267,72 +1277,72 @@ public function add_product_settings_tab_content() { ) ); - echo '
'; - echo '
'; - woocommerce_wp_radio( - array( - 'id' => 'fb_product_image_source', - 'label' => __( 'Facebook Product Image', 'facebook-for-woocommerce' ), - 'desc_tip' => true, - 'description' => __( 'Choose the product image that should be synced to the Facebook catalog and displayed for this product.', 'facebook-for-woocommerce' ), - 'options' => array( - Products::PRODUCT_IMAGE_SOURCE_PRODUCT => __( 'Use WooCommerce image', 'facebook-for-woocommerce' ), - Products::PRODUCT_IMAGE_SOURCE_CUSTOM => __( 'Use custom image', 'facebook-for-woocommerce' ), - ), - 'value' => $image_source ?: Products::PRODUCT_IMAGE_SOURCE_PRODUCT, - 'class' => 'short enable-if-sync-enabled js-fb-product-image-source', - 'wrapper_class' => 'fb-product-image-source-field', - ) - ); + woocommerce_wp_radio( + array( + 'id' => 'fb_product_image_source', + 'label' => __( 'Facebook Product Image', 'facebook-for-woocommerce' ), + 'desc_tip' => true, + 'description' => __( 'Choose the product image that should be synced to the Facebook catalog and displayed for this product.', 'facebook-for-woocommerce' ), + 'options' => array( + Products::PRODUCT_IMAGE_SOURCE_PRODUCT => __( 'Use WooCommerce image', 'facebook-for-woocommerce' ), + Products::PRODUCT_IMAGE_SOURCE_CUSTOM => __( 'Use custom image', 'facebook-for-woocommerce' ), + ), + 'value' => $image_source ? $image_source : Products::PRODUCT_IMAGE_SOURCE_PRODUCT, + 'class' => 'short enable-if-sync-enabled js-fb-product-image-source', + 'wrapper_class' => 'fb-product-image-source-field', + ) + ); - woocommerce_wp_text_input( - array( - 'id' => \WC_Facebook_Product::FB_PRODUCT_IMAGE, - 'label' => __( 'Custom Image URL', 'facebook-for-woocommerce' ), - 'value' => $image, - 'class' => sprintf( 'enable-if-sync-enabled product-image-source-field show-if-product-image-source-%s', Products::PRODUCT_IMAGE_SOURCE_CUSTOM ), - 'desc_tip' => true, - 'description' => __( 'Please enter an absolute URL (e.g. https://domain.com/image.jpg).', 'facebook-for-woocommerce' ), - ) - ); + woocommerce_wp_text_input( + array( + 'id' => \WC_Facebook_Product::FB_PRODUCT_IMAGE, + 'label' => __( 'Custom Image URL', 'facebook-for-woocommerce' ), + 'value' => $image, + 'class' => sprintf( 'enable-if-sync-enabled product-image-source-field show-if-product-image-source-%s', Products::PRODUCT_IMAGE_SOURCE_CUSTOM ), + 'desc_tip' => true, + 'description' => __( 'Please enter an absolute URL (e.g. https://domain.com/image.jpg).', 'facebook-for-woocommerce' ), + ) + ); $this->render_facebook_product_video_field( $video_urls ); - woocommerce_wp_text_input( - array( - 'id' => \WC_Facebook_Product::FB_PRODUCT_PRICE, - 'label' => sprintf( - /* translators: Placeholders %1$s - WC currency symbol */ - __( 'Facebook Price (%1$s)', 'facebook-for-woocommerce' ), - get_woocommerce_currency_symbol() - ), - 'desc_tip' => true, - 'description' => __( 'Custom price for product on Facebook. Please enter in monetary decimal (.) format without thousand separators and currency symbols. If blank, product price will be used.', 'facebook-for-woocommerce' ), - 'cols' => 40, - 'rows' => 60, - 'value' => $price, - 'class' => 'enable-if-sync-enabled', - ) - ); + woocommerce_wp_text_input( + array( + 'id' => \WC_Facebook_Product::FB_PRODUCT_PRICE, + 'label' => sprintf( + /* translators: Placeholders %1$s - WC currency symbol */ + __( 'Facebook Price (%1$s)', 'facebook-for-woocommerce' ), + get_woocommerce_currency_symbol() + ), + 'desc_tip' => true, + 'description' => __( 'Custom price for product on Facebook. Please enter in monetary decimal (.) format without thousand separators and currency symbols. If blank, product price will be used.', 'facebook-for-woocommerce' ), + 'cols' => 40, + 'rows' => 60, + 'value' => $price, + 'class' => 'enable-if-sync-enabled', + ) + ); woocommerce_wp_text_input( array( @@ -1358,7 +1368,7 @@ public function add_product_settings_tab_content() { 'value' => '', ) ); - ?> + ?>
@@ -1409,7 +1419,8 @@ public function add_product_variation_edit_fields( $index, $variation_data, $pos } $sync_enabled = 'no' !== $this->get_product_variation_meta( $variation, Products::SYNC_ENABLED_META_KEY, $parent ); - $is_visible = ( $visibility = $this->get_product_variation_meta( $variation, Products::VISIBILITY_META_KEY, $parent ) ) ? wc_string_to_bool( $visibility ) : true; + $visibility = $this->get_product_variation_meta( $variation, Products::VISIBILITY_META_KEY, $parent ); + $is_visible = $visibility ? wc_string_to_bool( $visibility ) : true; $description = $this->get_product_variation_meta( $variation, \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION, $parent ); $price = $this->get_product_variation_meta( $variation, \WC_Facebook_Product::FB_PRODUCT_PRICE, $parent ); $image_url = $this->get_product_variation_meta( $variation, \WC_Facebook_Product::FB_PRODUCT_IMAGE, $parent ); @@ -1440,22 +1451,22 @@ public function add_product_variation_edit_fields( $index, $variation_data, $pos ) ); - if ($variation->get_id() && $description) { - woocommerce_wp_textarea_input( - array( - 'id' => sprintf( 'variable_%s%s', \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION, $index ), - 'name' => sprintf( "variable_%s[$index]", \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION ), - 'label' => __( 'Facebook Description', 'facebook-for-woocommerce' ), - 'desc_tip' => true, - 'description' => __( 'Custom (plain-text only) description for product on Facebook. If blank, product description will be used. If product description is blank, shortname will be used.', 'facebook-for-woocommerce' ), - 'cols' => 40, - 'rows' => 5, - 'value' => $description, - 'class' => 'enable-if-sync-enabled', - 'wrapper_class' => 'form-row form-row-full', - ) - ); - } + if ( $variation->get_id() && $description ) { + woocommerce_wp_textarea_input( + array( + 'id' => sprintf( 'variable_%s%s', \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION, $index ), + 'name' => sprintf( "variable_%s[$index]", \WC_Facebookcommerce_Integration::FB_PRODUCT_DESCRIPTION ), + 'label' => __( 'Facebook Description', 'facebook-for-woocommerce' ), + 'desc_tip' => true, + 'description' => __( 'Custom (plain-text only) description for product on Facebook. If blank, product description will be used. If product description is blank, shortname will be used.', 'facebook-for-woocommerce' ), + 'cols' => 40, + 'rows' => 5, + 'value' => $description, + 'class' => 'enable-if-sync-enabled', + 'wrapper_class' => 'form-row form-row-full', + ) + ); + } woocommerce_wp_radio( array( @@ -1469,7 +1480,7 @@ public function add_product_variation_edit_fields( $index, $variation_data, $pos Products::PRODUCT_IMAGE_SOURCE_PARENT_PRODUCT => __( 'Use parent image', 'facebook-for-woocommerce' ), Products::PRODUCT_IMAGE_SOURCE_CUSTOM => __( 'Use custom image', 'facebook-for-woocommerce' ), ), - 'value' => $image_source ?: Products::PRODUCT_IMAGE_SOURCE_PRODUCT, + 'value' => $image_source ? $image_source : Products::PRODUCT_IMAGE_SOURCE_PRODUCT, 'class' => 'enable-if-sync-enabled js-fb-product-image-source', 'wrapper_class' => 'fb-product-image-source-field', ) @@ -1526,13 +1537,13 @@ public function add_product_variation_edit_fields( $index, $variation_data, $pos * * @param \WC_Product_Variation $variation the product variation * @param string $key the name of the meta to retrieve - * @param \WC_Product $parent the parent product + * @param \WC_Product $parent_product the parent product * @return mixed */ - private function get_product_variation_meta( $variation, $key, $parent ) { + private function get_product_variation_meta( $variation, $key, $parent_product ) { $value = $variation->get_meta( $key ); - if ( '' === $value && $parent instanceof \WC_Product ) { - $value = $parent->get_meta( $key ); + if ( '' === $value && $parent_product instanceof \WC_Product ) { + $value = $parent_product->get_meta( $key ); } return $value; } @@ -1553,13 +1564,13 @@ public function save_product_variation_edit_fields( $variation_id, $index ) { if ( ! $variation instanceof \WC_Product_Variation ) { return; } + // phpcs:disable WordPress.Security.NonceVerification.Missing $sync_mode = isset( $_POST['variable_facebook_sync_mode'][ $index ] ) ? wc_clean( wp_unslash( $_POST['variable_facebook_sync_mode'][ $index ] ) ) : self::SYNC_MODE_SYNC_DISABLED; $sync_enabled = self::SYNC_MODE_SYNC_DISABLED !== $sync_mode; if ( self::SYNC_MODE_SYNC_AND_SHOW === $sync_mode && $variation->is_virtual() ) { // force to Sync and hide $sync_mode = self::SYNC_MODE_SYNC_AND_HIDE; } - // phpcs:disable WordPress.Security.NonceVerification.Missing if ( $sync_enabled ) { Products::enable_sync_for_products( array( $variation ) ); Products::set_product_visibility( $variation, self::SYNC_MODE_SYNC_AND_HIDE !== $sync_mode );