Include sku partial match for products search.
This commit is contained in:
parent
9a71334fb1
commit
532c580081
|
@ -25,6 +25,9 @@ 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';
|
||||
|
||||
/**
|
||||
* Get the images for a product or product variation.
|
||||
*
|
||||
|
@ -70,6 +73,66 @@ class WC_REST_Products_Controller extends WC_REST_Products_V2_Controller {
|
|||
return $images;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a collection of products and add other search criteria to WP_Query.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @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_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 );
|
||||
}
|
||||
|
||||
$response = parent::get_items( $request );
|
||||
|
||||
// Remove filters for search criteria in product postmeta via the lookup table.
|
||||
if ( ! empty( $request[ $this->search_param ] ) ) {
|
||||
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 );
|
||||
}
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add in conditional search filters for products.
|
||||
*
|
||||
* @param string $where Where clause used to search posts.
|
||||
* @param object $wp_query WP_Query object.
|
||||
* @return string
|
||||
*/
|
||||
public static function add_search_criteria_to_wp_query_filter( $where, $wp_query ) {
|
||||
global $wpdb;
|
||||
$search = $wp_query->get( self::$wp_query_search_param );
|
||||
if ( ! empty( $search ) ) {
|
||||
$like_search = '%' . $wpdb->esc_like( $search ) . '%';
|
||||
$conditions = array(
|
||||
$wpdb->prepare( 'wc_product_meta_lookup.sku LIKE %s', $like_search ),
|
||||
);
|
||||
$where .= ' OR (' . implode( ' OR ', $conditions ) . ')';
|
||||
}
|
||||
return $where;
|
||||
}
|
||||
|
||||
/**
|
||||
* Join `wc_product_meta_lookup` table when product search query is present.
|
||||
*
|
||||
* @param string $join Join clause used to search posts.
|
||||
* @param object $wp_query WP_Query object.
|
||||
* @return string
|
||||
*/
|
||||
public static function add_search_criteria_to_wp_query_join( $join, $wp_query ) {
|
||||
global $wpdb;
|
||||
$search = $wp_query->get( self::$wp_query_search_param );
|
||||
if ( ! empty( $search ) ) {
|
||||
$join .= " LEFT JOIN {$wpdb->wc_product_meta_lookup} wc_product_meta_lookup
|
||||
ON $wpdb->posts.ID = wc_product_meta_lookup.product_id ";
|
||||
}
|
||||
return $join;
|
||||
}
|
||||
|
||||
/**
|
||||
* Make extra product orderby features supported by WooCommerce available to the WC API.
|
||||
* This includes 'price', 'popularity', and 'rating'.
|
||||
|
|
|
@ -147,4 +147,68 @@ class WC_REST_Products_Controller_Tests extends WC_REST_Unit_Test_Case {
|
|||
$this->assertContains( $field, $response_fields, "Field $field was expected but not present in product API response." );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that products with partial name or SKU case-insensitive match are returned given a `search` parameter.
|
||||
*/
|
||||
public function test_products_with_search_param_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',
|
||||
'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 the first product with full SKU case-insensitive match are returned given a `sku` parameter.
|
||||
*/
|
||||
public function test_products_with_sku_param_returns_the_first_product_with_full_sku_match() {
|
||||
// Given.
|
||||
wp_set_current_user( $this->user );
|
||||
WC_Helper_Product::create_simple_product( true, array( 'sku' => '0oWoO' ) );
|
||||
WC_Helper_Product::create_simple_product( true, array( 'sku' => 'WoO' ) );
|
||||
WC_Helper_Product::create_simple_product( true, array( 'sku' => 'woo' ) );
|
||||
WC_Helper_Product::create_simple_product( true, array( 'sku' => 'woo-sunglasses' ) );
|
||||
|
||||
// When.
|
||||
$request = new WP_REST_Request( 'GET', '/wc/v3/products' );
|
||||
$request->set_query_params(
|
||||
array(
|
||||
'sku' => 'woo',
|
||||
'order' => 'asc',
|
||||
'orderby' => 'id',
|
||||
)
|
||||
);
|
||||
$response = $this->server->dispatch( $request );
|
||||
$this->assertEquals( 200, $response->get_status() );
|
||||
$response_products = $response->get_data();
|
||||
|
||||
// Then.
|
||||
$this->assertEquals( 1, count( $response_products ) );
|
||||
$response_product = $response_products[0];
|
||||
$this->assertEquals( 'WoO', $response_product['sku'] );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue