Add a new parameter `search_includes_sku` so that SKU search isn't included by default.

This commit is contained in:
Jaclyn Chen 2022-03-09 14:46:09 +08:00 committed by Josh Betz
parent 532c580081
commit 49743f5167
2 changed files with 89 additions and 9 deletions

View File

@ -25,7 +25,6 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
*/
protected $namespace = 'wc/v3';
private $search_param = 'search';
private static $wp_query_search_param = 's';
/**
@ -80,8 +79,9 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
* @return WP_Error|WP_REST_Response
*/
public function get_items( $request ) {
// Add filters for search criteria in product postmeta via the lookup table.
if ( ! empty( $request[ $this->search_param ] ) ) {
// Add filters for search criteria in product postmeta via the lookup table.
$can_search_products_by_sku = $this->can_search_products_by_sku( $request );
if ( $can_search_products_by_sku ) {
add_filter( 'posts_where', array( __CLASS__, 'add_search_criteria_to_wp_query_filter' ), 10, 2 );
add_filter( 'posts_join', array( __CLASS__, 'add_search_criteria_to_wp_query_join' ), 10, 2 );
}
@ -89,7 +89,7 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
$response = parent::get_items( $request );
// Remove filters for search criteria in product postmeta via the lookup table.
if ( ! empty( $request[ $this->search_param ] ) ) {
if ( $can_search_products_by_sku ) {
remove_filter( 'posts_where', array( __CLASS__, 'add_search_criteria_to_wp_query_filter' ), 10 );
remove_filter( 'posts_join', array( __CLASS__, 'add_search_criteria_to_wp_query_join' ), 10 );
}
@ -1431,6 +1431,13 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
'validate_callback' => 'rest_validate_request_arg',
);
$params['search_includes_sku'] = array(
'description' => __( 'When `search` parameter is set, whether to also search products by partial SKU.', 'woocommerce' ),
'type' => 'boolean',
'sanitize_callback' => 'wc_string_to_bool',
'validate_callback' => 'rest_validate_request_arg',
);
return $params;
}
@ -1456,4 +1463,14 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
}
return $data;
}
/**
* Determine whether products search should include SKU.
*
* @param WP_REST_Request $request Full details about the request.
* @return bool Whether SKU can be included in products search.
*/
private function can_search_products_by_sku( WP_REST_Request $request ) {
return ! empty( $request['search'] ) && $request['search_includes_sku'] && wc_product_sku_enabled();
}
}

View File

@ -149,9 +149,44 @@ class WC_REST_Products_Controller_Tests extends WC_REST_Unit_Test_Case {
}
/**
* Test that products with partial name or SKU case-insensitive match are returned given a `search` parameter.
* Test that products with partial name or SKU case-insensitive match are returned given both `search` and `search_includes_sku` parameters.
*/
public function test_products_with_search_param_returns_products_with_sku_and_name_match() {
public function test_products_with_search_param_including_sku_returns_products_with_sku_and_name_match() {
// Given.
wp_set_current_user( $this->user );
WC_Helper_Product::create_simple_product( true, array( 'name' => 'WooCommerce Tests' ) );
WC_Helper_Product::create_simple_product( true, array( 'name' => 'WordCamp' ) );
WC_Helper_Product::create_simple_product( true, array( 'name' => 'WoO' ) );
WC_Helper_Product::create_simple_product( true, array( 'sku' => 'Woo' ) );
WC_Helper_Product::create_simple_product( true, array( 'sku' => 'wordpress' ) );
WC_Helper_Product::create_simple_product( true, array( 'sku' => '*sunglasses-woo*' ) );
// When.
$request = new WP_REST_Request( 'GET', '/wc/v3/products' );
$request->set_query_params(
array(
'search' => 'woo',
'search_includes_sku' => true,
'order' => 'asc',
'orderby' => 'id',
)
);
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$response_products = $response->get_data();
// Then.
$this->assertEquals( 4, count( $response_products ) );
$this->assertEquals( $response_products[0]['name'], 'WooCommerce Tests' );
$this->assertEquals( $response_products[1]['name'], 'WoO' );
$this->assertEquals( $response_products[2]['sku'], 'Woo' );
$this->assertEquals( $response_products[3]['sku'], '*sunglasses-woo*' );
}
/**
* Test that only products with name match are returned given `search` without `search_includes_sku` parameter.
*/
public function test_products_with_search_param_only_returns_products_with_name_match() {
// Given.
wp_set_current_user( $this->user );
WC_Helper_Product::create_simple_product( true, array( 'name' => 'WooCommerce Tests' ) );
@ -175,11 +210,39 @@ class WC_REST_Products_Controller_Tests extends WC_REST_Unit_Test_Case {
$response_products = $response->get_data();
// Then.
$this->assertEquals( 4, count( $response_products ) );
$this->assertEquals( 2, count( $response_products ) );
$this->assertEquals( $response_products[0]['name'], 'WooCommerce Tests' );
$this->assertEquals( $response_products[1]['name'], 'WoO' );
$this->assertEquals( $response_products[2]['sku'], 'Woo' );
$this->assertEquals( $response_products[3]['sku'], '*sunglasses-woo*' );
}
/**
* Test that no products with SKU are returned given `search` and `search_includes_sku` parameters when product SKU is disabled.
*/
public function test_products_with_search_param_including_sku_returns_no_products_when_sku_is_disabled() {
// Given.
wp_set_current_user( $this->user );
WC_Helper_Product::create_simple_product( true, array( 'sku' => 'Woo' ) );
WC_Helper_Product::create_simple_product( true, array( 'sku' => 'wordpress' ) );
WC_Helper_Product::create_simple_product( true, array( 'sku' => '*sunglasses-woo*' ) );
// When.
add_filter( 'wc_product_sku_enabled', '__return_false' );
$request = new WP_REST_Request( 'GET', '/wc/v3/products' );
$request->set_query_params(
array(
'search' => 'woo',
'search_includes_sku' => true,
'order' => 'asc',
'orderby' => 'id',
)
);
$response = $this->server->dispatch( $request );
$this->assertEquals( 200, $response->get_status() );
$response_products = $response->get_data();
// Then.
$this->assertEquals( 0, count( $response_products ) );
}
/**