Skip to content

Commit

Permalink
fix customer search for email and username
Browse files Browse the repository at this point in the history
  • Loading branch information
kilbot committed Nov 17, 2023
1 parent 1223b14 commit 2482efa
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 41 deletions.
149 changes: 113 additions & 36 deletions includes/API/Customers_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ class Customers_Controller extends WC_REST_Customers_Controller {
*/
protected $namespace = 'wcpos/v1';

/**
* Store user search results for merging with meta_query search results.
*
* @var array
*/
protected $wcpos_user_search_results = array();

/**
* Constructor.
*/
Expand Down Expand Up @@ -259,11 +266,9 @@ public function wcpos_get_all_posts( array $fields = array() ): array {
}
}

/**
/*
* Filter arguments, before passing to WP_User_Query, when querying users via the REST API.
*
* @see https://developer.wordpress.org/reference/classes/wp_user_query/
*
* @param array $prepared_args Array of arguments for WP_User_Query.
* @param WP_REST_Request $request The current request.
*
Expand All @@ -287,39 +292,6 @@ public function wcpos_customer_query( array $prepared_args, WP_REST_Request $req
);
}

// If the 'search' parameter exists
if ( isset( $query_params['search'] ) && ! empty( $query_params['search'] ) ) {
$search_keyword = $query_params['search'];

$search_meta_query = array(
'relation' => 'OR',
array(
'key' => 'first_name',
'value' => $search_keyword,
'compare' => 'LIKE',
),
array(
'key' => 'last_name',
'value' => $search_keyword,
'compare' => 'LIKE',
),
);

// Merge with existing meta_query if any
if ( ! empty($existing_meta_query)) {
$existing_meta_query = array(
'relation' => 'AND',
$existing_meta_query,
$search_meta_query,
);
} else {
$existing_meta_query = $search_meta_query;
}
}

// Apply the modified or newly created meta_query
$prepared_args['meta_query'] = $existing_meta_query;

// Handle orderby cases
if ( isset( $query_params['orderby'] ) ) {
switch ( $query_params['orderby'] ) {
Expand Down Expand Up @@ -356,6 +328,111 @@ public function wcpos_customer_query( array $prepared_args, WP_REST_Request $req
}
}

// Handle search
if ( isset( $query_params['search'] ) && ! empty( $query_params['search'] ) ) {
$search_keyword = $query_params['search'];

/*
* It seems that you can't search by user_email, user_login etc and meta_query at the same time.
*
* We will unset the search param and add a hook to modify the user query to search the user table
*/
unset( $prepared_args['search'] );
$prepared_args['_wcpos_search'] = $search_keyword; // store the search keyword for later use
add_action( 'pre_user_query', array( $this, 'wcpos_search_user_table' ) );

$search_meta_query = array(
'relation' => 'OR',
array(
'key' => 'first_name',
'value' => $search_keyword,
'compare' => 'LIKE',
),
array(
'key' => 'last_name',
'value' => $search_keyword,
'compare' => 'LIKE',
),
// WooCommerce billing fields
array(
'key' => 'billing_first_name',
'value' => $search_keyword,
'compare' => 'LIKE',
),
array(
'key' => 'billing_last_name',
'value' => $search_keyword,
'compare' => 'LIKE',
),
array(
'key' => 'billing_email',
'value' => $search_keyword,
'compare' => 'LIKE',
),
array(
'key' => 'billing_company',
'value' => $search_keyword,
'compare' => 'LIKE',
),
array(
'key' => 'billing_phone',
'value' => $search_keyword,
'compare' => 'LIKE',
),
);

// Merge with existing meta_query if any
if ( ! empty($existing_meta_query)) {
$existing_meta_query = array(
'relation' => 'AND',
$existing_meta_query,
$search_meta_query,
);
} else {
$existing_meta_query = $search_meta_query;
}
}

// Apply the modified or newly created meta_query
$prepared_args['meta_query'] = $existing_meta_query;

return $prepared_args;
}

/**
* Add user_email and user_login to the user query.
*
* @param WP_User_Query $query
*/
public function wcpos_search_user_table( $query ): void {
global $wpdb;

// Remove the hook
remove_action( 'pre_user_query', array( $this, 'wcpos_search_user_table' ) );

// Get the search keyword
$query_params = $query->query_vars;
$search_keyword = $query_params['_wcpos_search'];

// Prepare the LIKE statement
$like_email = '%' . $wpdb->esc_like( $search_keyword ) . '%';
$like_login = '%' . $wpdb->esc_like( $search_keyword ) . '%';

$insertion = $wpdb->prepare(
"({$wpdb->users}.user_email LIKE %s) OR ({$wpdb->users}.user_login LIKE %s) OR ",
$like_email,
$like_login
);

//$insertion = "({$wpdb->users}.user_email LIKE '%" . $search_keyword . "%') OR ({$wpdb->users}.user_login LIKE '%" . $search_keyword . "%') OR ";
$pattern = "/\(\s*\w+\.meta_key\s*=\s*'[^']+'\s*AND\s*\w+\.meta_value\s*LIKE\s*'[^']+'\s*\)(\s*OR\s*\(\s*\w+\.meta_key\s*=\s*'[^']+'\s*AND\s*\w+\.meta_value\s*LIKE\s*'[^']+'\s*\))*\s*/";

// Add the search keyword to the query
$modified_where = preg_replace($pattern, "$insertion$0", $query->query_where);
// Check if the replacement was successful and assign it back to query_where
if ($modified_where !== $query->query_where) {
$query->query_where = $modified_where;
}
}
}
21 changes: 16 additions & 5 deletions tests/includes/API/Test_Customers_Controller.php
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@ public function test_customer_search(): void {
$random_username = wp_generate_password(6, false);
$random_billing_first_name = wp_generate_password(8, false);
$random_billing_last_name = wp_generate_password(8, false);
$random_billing_email = wp_generate_password(8, false) . '@test.com';
$random_billing_company = wp_generate_password(8, false);
$random_billing_phone = wp_generate_password(8, false);

Expand All @@ -284,17 +285,19 @@ public function test_customer_search(): void {
$customer4 = CustomerHelper::create_customer( array( 'username' => $random_username ) );
$customer5 = CustomerHelper::create_customer( array( 'billing_first_name' => $random_billing_first_name ) );
$customer6 = CustomerHelper::create_customer( array( 'billing_last_name' => $random_billing_last_name ) );
$customer7 = CustomerHelper::create_customer( array( 'billing_company' => $random_billing_company ) );
$customer8 = CustomerHelper::create_customer( array( 'billing_phone' => $random_billing_phone ) );
$customer7 = CustomerHelper::create_customer( array( 'billing_email' => $random_billing_email ) );
$customer8 = CustomerHelper::create_customer( array( 'billing_company' => $random_billing_company ) );
$customer9 = CustomerHelper::create_customer( array( 'billing_phone' => $random_billing_phone ) );

$request = $this->wp_rest_get_request( '/wcpos/v1/customers' );
$request->set_query_params( array( 'role' => 'all' ) );

// empty search
$request->set_query_params( array( 'search' => '' ) );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertEquals(200, $response->get_status());
$this->assertEquals( 8, \count( $data ) );
$this->assertEquals( 9, \count( $data ) );

// search for first_name
$request->set_query_params( array( 'search' => $random_first_name ) );
Expand Down Expand Up @@ -344,21 +347,29 @@ public function test_customer_search(): void {
$this->assertEquals( 1, \count( $data ) );
$this->assertEquals( $customer6->get_id(), $data[0]['id'] );

// search for billing_last_name
$request->set_query_params( array( 'search' => $random_billing_email ) );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertEquals(200, $response->get_status());
$this->assertEquals( 1, \count( $data ) );
$this->assertEquals( $customer7->get_id(), $data[0]['id'] );

// search for billing_company
$request->set_query_params( array( 'search' => $random_billing_company ) );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertEquals(200, $response->get_status());
$this->assertEquals( 1, \count( $data ) );
$this->assertEquals( $customer7->get_id(), $data[0]['id'] );
$this->assertEquals( $customer8->get_id(), $data[0]['id'] );

// search for billing_last_name
$request->set_query_params( array( 'search' => $random_billing_phone ) );
$response = rest_get_server()->dispatch( $request );
$data = $response->get_data();
$this->assertEquals(200, $response->get_status());
$this->assertEquals( 1, \count( $data ) );
$this->assertEquals( $customer8->get_id(), $data[0]['id'] );
$this->assertEquals( $customer9->get_id(), $data[0]['id'] );
}

/**
Expand Down

0 comments on commit 2482efa

Please sign in to comment.