From 928ec871fa9c1d82aeb59cb543682cb8da1f0fab Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Fri, 29 Nov 2019 17:06:33 -0800 Subject: [PATCH 1/5] Code style fixes --- includes/class-wc-ajax.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/includes/class-wc-ajax.php b/includes/class-wc-ajax.php index 3383cc03608..63be71a3304 100644 --- a/includes/class-wc-ajax.php +++ b/includes/class-wc-ajax.php @@ -74,7 +74,7 @@ class WC_AJAX { public static function do_wc_ajax() { global $wp_query; - // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification + // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( ! empty( $_GET['wc-ajax'] ) ) { $wp_query->set( 'wc-ajax', sanitize_text_field( wp_unslash( $_GET['wc-ajax'] ) ) ); } @@ -396,7 +396,7 @@ class WC_AJAX { public static function add_to_cart() { ob_start(); - // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification + // phpcs:disable WordPress.Security.NonceVerification.Missing if ( ! isset( $_POST['product_id'] ) ) { return; } @@ -444,7 +444,7 @@ class WC_AJAX { public static function remove_from_cart() { ob_start(); - // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification + // phpcs:ignore WordPress.Security.NonceVerification.Missing $cart_item_key = wc_clean( isset( $_POST['cart_item_key'] ) ? wp_unslash( $_POST['cart_item_key'] ) : '' ); if ( $cart_item_key && false !== WC()->cart->remove_cart_item( $cart_item_key ) ) { @@ -469,7 +469,7 @@ class WC_AJAX { public static function get_variation() { ob_start(); - // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification + // phpcs:disable WordPress.Security.NonceVerification.Missing if ( empty( $_POST['product_id'] ) ) { wp_die(); } @@ -1144,7 +1144,7 @@ class WC_AJAX { $order->set_billing_email( $user_email_arg ); } - $result = $order->apply_coupon( wc_format_coupon_code( wp_unslash( $_POST['coupon'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + $result = $order->apply_coupon( wc_format_coupon_code( wp_unslash( $_POST['coupon'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized if ( is_wp_error( $result ) ) { throw new Exception( html_entity_decode( wp_strip_all_tags( $result->get_error_message() ) ) ); @@ -1196,7 +1196,7 @@ class WC_AJAX { throw new Exception( __( 'Invalid coupon', 'woocommerce' ) ); } - $order->remove_coupon( wc_format_coupon_code( wp_unslash( $_POST['coupon'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.NoNonceVerification, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + $order->remove_coupon( wc_format_coupon_code( wp_unslash( $_POST['coupon'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $order->calculate_taxes( $calculate_tax_args ); $order->calculate_totals( false ); @@ -1717,7 +1717,7 @@ class WC_AJAX { * Ajax request handling for categories ordering. */ public static function term_ordering() { - // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification + // phpcs:disable WordPress.Security.NonceVerification.Missing if ( ! current_user_can( 'edit_products' ) || empty( $_POST['id'] ) ) { wp_die( -1 ); } @@ -1750,7 +1750,7 @@ class WC_AJAX { public static function product_ordering() { global $wpdb; - // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification + // phpcs:disable WordPress.Security.NonceVerification.Missing if ( ! current_user_can( 'edit_products' ) || empty( $_POST['id'] ) ) { wp_die( -1 ); } @@ -2536,7 +2536,7 @@ class WC_AJAX { * Handle submissions from assets/js/settings-views-html-settings-tax.js Backbone model. */ public static function tax_rates_save_changes() { - // phpcs:disable WordPress.Security.NonceVerification.NoNonceVerification + // phpcs:disable WordPress.Security.NonceVerification.Missing if ( ! isset( $_POST['wc_tax_nonce'], $_POST['changes'] ) ) { wp_send_json_error( 'missing_fields' ); wp_die(); From baeae0652c6c12e658ae798502026e30397e4621 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Fri, 29 Nov 2019 17:06:50 -0800 Subject: [PATCH 2/5] Added a check to prevent variable product parents from being added to orders. --- includes/class-wc-ajax.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/includes/class-wc-ajax.php b/includes/class-wc-ajax.php index 63be71a3304..48a7eef227b 100644 --- a/includes/class-wc-ajax.php +++ b/includes/class-wc-ajax.php @@ -898,6 +898,10 @@ class WC_AJAX { if ( ! $product ) { throw new Exception( __( 'Invalid product ID', 'woocommerce' ) . ' ' . $product_id ); } + if ( 'variable' === $product->get_type() ) { + /* translators: %s product name */ + throw new Exception( sprintf( __( '%s is a variable product parent and cannot be added.', 'woocommerce' ), $product->get_name() ) ); + } $validation_error = new WP_Error(); $validation_error = apply_filters( 'woocommerce_ajax_add_order_item_validation', $validation_error, $product, $order, $qty ); From d1e25c9118aae12daf6be27255ccc1e787f5bb84 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Tue, 3 Dec 2019 14:14:47 -0800 Subject: [PATCH 3/5] Added support for excluding certain product types from AJAX product searches --- assets/js/admin/wc-enhanced-select.js | 7 +++++-- includes/class-wc-ajax.php | 13 +++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/assets/js/admin/wc-enhanced-select.js b/assets/js/admin/wc-enhanced-select.js index 5438085a90d..4eac44f6371 100644 --- a/assets/js/admin/wc-enhanced-select.js +++ b/assets/js/admin/wc-enhanced-select.js @@ -91,6 +91,7 @@ jQuery( function( $ ) { action : $( this ).data( 'action' ) || 'woocommerce_json_search_products_and_variations', security : wc_enhanced_select_params.search_products_nonce, exclude : $( this ).data( 'exclude' ), + exclude_type : $( this ).data( 'exclude_type' ), include : $( this ).data( 'include' ), limit : $( this ).data( 'limit' ), display_stock: $( this ).data( 'display_stock' ) @@ -260,14 +261,16 @@ jQuery( function( $ ) { // WooCommerce Backbone Modal .on( 'wc_backbone_modal_before_remove', function() { - $( '.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search' ).filter( '.select2-hidden-accessible' ).selectWoo( 'close' ); + $( '.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search' ).filter( '.select2-hidden-accessible' ) + .selectWoo( 'close' ); }) .trigger( 'wc-enhanced-select-init' ); $( 'html' ).on( 'click', function( event ) { if ( this === event.target ) { - $( '.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search' ).filter( '.select2-hidden-accessible' ).selectWoo( 'close' ); + $( '.wc-enhanced-select, :input.wc-product-search, :input.wc-customer-search' ).filter( '.select2-hidden-accessible' ) + .selectWoo( 'close' ); } } ); } catch( err ) { diff --git a/includes/class-wc-ajax.php b/includes/class-wc-ajax.php index 48a7eef227b..d1e3b534d26 100644 --- a/includes/class-wc-ajax.php +++ b/includes/class-wc-ajax.php @@ -1540,6 +1540,15 @@ class WC_AJAX { $include_ids = ! empty( $_GET['include'] ) ? array_map( 'absint', (array) wp_unslash( $_GET['include'] ) ) : array(); $exclude_ids = ! empty( $_GET['exclude'] ) ? array_map( 'absint', (array) wp_unslash( $_GET['exclude'] ) ) : array(); + if ( ! empty( $_GET['exclude_type'] ) ) { + $exclude_types = array_map( 'strtolower', (array) wp_unslash( $_GET['exclude_type'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + + // Sanitize the excluded types against valid product types. + $exclude_types = array_intersect( array_keys( wc_get_product_types() ), $exclude_types ); + } else { + $exclude_types = array(); + } + $data_store = WC_Data_Store::load( 'product' ); $ids = $data_store->search_products( $term, '', (bool) $include_variations, false, $limit, $include_ids, $exclude_ids ); @@ -1550,6 +1559,10 @@ class WC_AJAX { $formatted_name = $product_object->get_formatted_name(); $managing_stock = $product_object->managing_stock(); + if ( in_array( $product_object->get_type(), $exclude_types, true ) ) { + continue; + } + if ( $managing_stock && ! empty( $_GET['display_stock'] ) ) { $stock_amount = $product_object->get_stock_quantity(); /* Translators: %d stock amount */ From d3a72668485e9b2471c62a03e9446bd0401e0c44 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Tue, 3 Dec 2019 14:17:51 -0800 Subject: [PATCH 4/5] Hid variable product types from "Add Products" search on order management page --- includes/admin/meta-boxes/views/html-order-items.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/meta-boxes/views/html-order-items.php b/includes/admin/meta-boxes/views/html-order-items.php index 04434aeccd8..99f684288a8 100644 --- a/includes/admin/meta-boxes/views/html-order-items.php +++ b/includes/admin/meta-boxes/views/html-order-items.php @@ -345,7 +345,7 @@ if ( wc_tax_enabled() ) { + '; ?> From b67d0946012036d593a46237e8902b7068ffe113 Mon Sep 17 00:00:00 2001 From: Christopher Allford Date: Wed, 4 Dec 2019 14:39:41 -0800 Subject: [PATCH 5/5] Added support for comma-delimited lists of types to exclude --- includes/class-wc-ajax.php | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/includes/class-wc-ajax.php b/includes/class-wc-ajax.php index d1e3b534d26..cace806e0a1 100644 --- a/includes/class-wc-ajax.php +++ b/includes/class-wc-ajax.php @@ -1540,13 +1540,22 @@ class WC_AJAX { $include_ids = ! empty( $_GET['include'] ) ? array_map( 'absint', (array) wp_unslash( $_GET['include'] ) ) : array(); $exclude_ids = ! empty( $_GET['exclude'] ) ? array_map( 'absint', (array) wp_unslash( $_GET['exclude'] ) ) : array(); + $exclude_types = array(); if ( ! empty( $_GET['exclude_type'] ) ) { - $exclude_types = array_map( 'strtolower', (array) wp_unslash( $_GET['exclude_type'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + // Support both comma-delimited and array format inputs. + $exclude_types = wp_unslash( $_GET['exclude_type'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized + if ( ! is_array( $exclude_types ) ) { + $exclude_types = explode( ',', $exclude_types ); + } // Sanitize the excluded types against valid product types. - $exclude_types = array_intersect( array_keys( wc_get_product_types() ), $exclude_types ); - } else { - $exclude_types = array(); + foreach ( $exclude_types as &$exclude_type ) { + $exclude_type = strtolower( trim( $exclude_type ) ); + } + $exclude_types = array_intersect( + array_merge( array( 'variation' ), array_keys( wc_get_product_types() ) ), + $exclude_types + ); } $data_store = WC_Data_Store::load( 'product' );