Commit cdf2cc690e4 for woocommerce
commit cdf2cc690e4dec565d32498883f27a4152d7e089
Author: Mike Jolley <mike.jolley@me.com>
Date: Fri Mar 6 15:58:39 2026 +0000
Fix customers report includes/excludes params incorrectly filtering by `customer_id` (#63232)
* Update datastore to look at correct columns
* Expand test coverage
* Add changefile(s) from automation for the following project(s): woocommerce
* Make client search by strings rather than client ids
* Allow for either strings or IDs when using includes/excludes filter
* Add changefile(s) from automation for the following project(s): woocommerce
* Fix customer ID merging
---------
Co-authored-by: woocommercebot <woocommercebot@users.noreply.github.com>
diff --git a/plugins/woocommerce/changelog/63232-fix-customer-reports-datastore-include-exclude-params b/plugins/woocommerce/changelog/63232-fix-customer-reports-datastore-include-exclude-params
new file mode 100644
index 00000000000..35cb162e90a
--- /dev/null
+++ b/plugins/woocommerce/changelog/63232-fix-customer-reports-datastore-include-exclude-params
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix Customers Reports advanced filters (email, username, name) by consolidating autocompleter customer IDs into customers/customers_exclude params in the Controller, and add customers_exclude support.
\ No newline at end of file
diff --git a/plugins/woocommerce/src/Admin/API/Reports/Customers/Controller.php b/plugins/woocommerce/src/Admin/API/Reports/Customers/Controller.php
index 0d612929051..b4de6656e0e 100644
--- a/plugins/woocommerce/src/Admin/API/Reports/Customers/Controller.php
+++ b/plugins/woocommerce/src/Admin/API/Reports/Customers/Controller.php
@@ -84,6 +84,7 @@ class Controller extends GenericController implements ExportableInterface {
$args['last_order_before'] = $request['last_order_before'];
$args['last_order_after'] = $request['last_order_after'];
$args['customers'] = $request['customers'];
+ $args['customers_exclude'] = $request['customers_exclude'];
$args['users'] = $request['users'];
$args['force_cache_refresh'] = $request['force_cache_refresh'];
$args['filter_empty'] = $request['filter_empty'];
@@ -97,9 +98,104 @@ class Controller extends GenericController implements ExportableInterface {
$normalized_params_date = TimeInterval::normalize_between_params( $request, $between_params_date, true );
$args = array_merge( $args, $normalized_params_numeric, $normalized_params_date );
+ $args = self::consolidate_customer_id_filters( $args );
+
+ return $args;
+ }
+
+ /**
+ * Consolidate customer identity filter IDs into customers/customers_exclude.
+ *
+ * When the frontend sends customer IDs via name_includes, email_includes, or
+ * username_includes, this method collects those IDs and merges them into the
+ * customers/customers_exclude params so the DataStore filters by customer_id.
+ *
+ * Only numeric values are consolidated. String values (e.g. actual email
+ * addresses or names) are left untouched for the DataStore's exact-match
+ * filtering.
+ *
+ * @param array $args Query arguments.
+ * @return array Modified query arguments.
+ */
+ public static function consolidate_customer_id_filters( $args ) {
+ $include_params = array( 'name_includes', 'email_includes', 'username_includes' );
+ $exclude_params = array( 'name_excludes', 'email_excludes', 'username_excludes' );
+ $match = $args['match'] ?? 'all';
+
+ $include_sets = array();
+ foreach ( $include_params as $param ) {
+ if ( ! empty( $args[ $param ] ) && self::is_id_list( $args[ $param ] ) ) {
+ $include_sets[] = wp_parse_id_list( $args[ $param ] );
+ $args[ $param ] = null;
+ }
+ }
+ if ( ! empty( $include_sets ) ) {
+ $consolidated = count( $include_sets ) > 1
+ ? ( 'all' === $match
+ ? call_user_func_array( 'array_intersect', $include_sets )
+ : array_unique( array_merge( ...$include_sets ) ) )
+ : $include_sets[0];
+
+ // Merge with any pre-existing customers filter.
+ if ( ! empty( $args['customers'] ) ) {
+ $existing = wp_parse_id_list( $args['customers'] );
+ $consolidated = 'all' === $match
+ ? array_intersect( $consolidated, $existing )
+ : array_unique( array_merge( $consolidated, $existing ) );
+ }
+
+ // When match=all and intersection is empty, force no-results.
+ $args['customers'] = empty( $consolidated ) ? array( 0 ) : array_values( $consolidated );
+ }
+
+ $exclude_sets = array();
+ foreach ( $exclude_params as $param ) {
+ if ( ! empty( $args[ $param ] ) && self::is_id_list( $args[ $param ] ) ) {
+ $exclude_sets[] = wp_parse_id_list( $args[ $param ] );
+ $args[ $param ] = null;
+ }
+ }
+ if ( ! empty( $exclude_sets ) ) {
+ $consolidated = count( $exclude_sets ) > 1
+ ? ( 'all' === $match
+ ? array_unique( array_merge( ...$exclude_sets ) )
+ : call_user_func_array( 'array_intersect', $exclude_sets ) )
+ : $exclude_sets[0];
+
+ // Merge with any pre-existing customers_exclude filter.
+ if ( ! empty( $args['customers_exclude'] ) ) {
+ $existing = wp_parse_id_list( $args['customers_exclude'] );
+ $consolidated = array_unique( array_merge( $consolidated, $existing ) );
+ }
+
+ $args['customers_exclude'] = array_values( $consolidated );
+ }
+
return $args;
}
+ /**
+ * Check if a value is a comma-separated list of numeric IDs.
+ *
+ * @param mixed $value The value to check.
+ * @return bool True if the value contains only numeric IDs.
+ */
+ private static function is_id_list( $value ) {
+ if ( is_array( $value ) ) {
+ $values = $value;
+ } elseif ( is_string( $value ) ) {
+ $values = explode( ',', $value );
+ } else {
+ return false;
+ }
+ foreach ( $values as $v ) {
+ if ( ! is_numeric( trim( $v ) ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
/**
* Get one report.
*
@@ -529,6 +625,15 @@ class Controller extends GenericController implements ExportableInterface {
'type' => 'integer',
),
);
+ $params['customers_exclude'] = array(
+ 'description' => __( 'Limit result to exclude items with specified customer ids.', 'woocommerce' ),
+ 'type' => 'array',
+ 'sanitize_callback' => 'wp_parse_id_list',
+ 'validate_callback' => 'rest_validate_request_arg',
+ 'items' => array(
+ 'type' => 'integer',
+ ),
+ );
$params['users'] = array(
'description' => __( 'Limit result to items with specified user ids.', 'woocommerce' ),
'type' => 'array',
diff --git a/plugins/woocommerce/src/Admin/API/Reports/Customers/DataStore.php b/plugins/woocommerce/src/Admin/API/Reports/Customers/DataStore.php
index 57e9772dd8d..b3a39e6d110 100644
--- a/plugins/woocommerce/src/Admin/API/Reports/Customers/DataStore.php
+++ b/plugins/woocommerce/src/Admin/API/Reports/Customers/DataStore.php
@@ -309,29 +309,25 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
$having_clauses = array();
$exact_match_params = array(
- 'name',
- 'username',
- 'email',
- 'country',
+ 'name' => "CONCAT_WS( ' ', {$customer_lookup_table}.first_name, {$customer_lookup_table}.last_name )",
+ 'username' => "{$customer_lookup_table}.username",
+ 'email' => "{$customer_lookup_table}.email",
+ 'country' => "{$customer_lookup_table}.country",
);
- foreach ( $exact_match_params as $exact_match_param ) {
+ foreach ( $exact_match_params as $exact_match_param => $column_expression ) {
if ( ! empty( $query_args[ $exact_match_param . '_includes' ] ) ) {
$exact_match_arguments = $query_args[ $exact_match_param . '_includes' ];
$exact_match_arguments_escaped = array_map( 'esc_sql', explode( ',', $exact_match_arguments ) );
$included = implode( "','", $exact_match_arguments_escaped );
- // 'country_includes' is a list of country codes, the others will be a list of customer ids.
- $table_column = 'country' === $exact_match_param ? $exact_match_param : 'customer_id';
- $where_clauses[] = "{$customer_lookup_table}.{$table_column} IN ('{$included}')";
+ $where_clauses[] = "{$column_expression} IN ('{$included}')";
}
if ( ! empty( $query_args[ $exact_match_param . '_excludes' ] ) ) {
$exact_match_arguments = $query_args[ $exact_match_param . '_excludes' ];
$exact_match_arguments_escaped = array_map( 'esc_sql', explode( ',', $exact_match_arguments ) );
$excluded = implode( "','", $exact_match_arguments_escaped );
- // 'country_includes' is a list of country codes, the others will be a list of customer ids.
- $table_column = 'country' === $exact_match_param ? $exact_match_param : 'customer_id';
- $where_clauses[] = "{$customer_lookup_table}.{$table_column} NOT IN ('{$excluded}')";
+ $where_clauses[] = "{$column_expression} NOT IN ('{$excluded}')";
}
}
@@ -386,6 +382,12 @@ class DataStore extends ReportsDataStore implements DataStoreInterface {
$where_clauses[] = "{$customer_lookup_table}.customer_id IN ({$included_customers})";
}
+ // Allow a list of customer IDs to be excluded.
+ if ( ! empty( $query_args['customers_exclude'] ) ) {
+ $excluded_customers = $this->get_filtered_ids( $query_args, 'customers_exclude' );
+ $where_clauses[] = "{$customer_lookup_table}.customer_id NOT IN ({$excluded_customers})";
+ }
+
// Allow a list of user IDs to be specified.
if ( ! empty( $query_args['users'] ) ) {
$included_users = $this->get_filtered_ids( $query_args, 'users' );
diff --git a/plugins/woocommerce/src/Admin/API/Reports/Customers/Stats/Controller.php b/plugins/woocommerce/src/Admin/API/Reports/Customers/Stats/Controller.php
index 3b1b201e50f..e99d685d2fd 100644
--- a/plugins/woocommerce/src/Admin/API/Reports/Customers/Stats/Controller.php
+++ b/plugins/woocommerce/src/Admin/API/Reports/Customers/Stats/Controller.php
@@ -8,6 +8,7 @@
namespace Automattic\WooCommerce\Admin\API\Reports\Customers\Stats;
use Automattic\WooCommerce\Admin\API\Reports\Customers\Query;
+use Automattic\WooCommerce\Admin\API\Reports\Customers\Controller as CustomersController;
defined( 'ABSPATH' ) || exit;
@@ -65,6 +66,7 @@ class Controller extends \WC_REST_Reports_Controller {
$args['last_order_before'] = $request['last_order_before'];
$args['last_order_after'] = $request['last_order_after'];
$args['customers'] = $request['customers'];
+ $args['customers_exclude'] = $request['customers_exclude'];
$args['fields'] = $request['fields'];
$args['force_cache_refresh'] = $request['force_cache_refresh'];
@@ -74,6 +76,8 @@ class Controller extends \WC_REST_Reports_Controller {
$normalized_params_date = TimeInterval::normalize_between_params( $request, $between_params_date, true );
$args = array_merge( $args, $normalized_params_numeric, $normalized_params_date );
+ $args = CustomersController::consolidate_customer_id_filters( $args );
+
return $args;
}
@@ -380,6 +384,15 @@ class Controller extends \WC_REST_Reports_Controller {
'type' => 'integer',
),
);
+ $params['customers_exclude'] = array(
+ 'description' => __( 'Limit result to exclude items with specified customer ids.', 'woocommerce' ),
+ 'type' => 'array',
+ 'sanitize_callback' => 'wp_parse_id_list',
+ 'validate_callback' => 'rest_validate_request_arg',
+ 'items' => array(
+ 'type' => 'integer',
+ ),
+ );
$params['fields'] = array(
'description' => __( 'Limit stats fields to the specified items.', 'woocommerce' ),
'type' => 'array',
diff --git a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-reports-customers-controller-test.php b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-reports-customers-controller-test.php
index 1961b5655d1..6d53c3667bc 100644
--- a/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-reports-customers-controller-test.php
+++ b/plugins/woocommerce/tests/php/includes/admin/class-wc-admin-reports-customers-controller-test.php
@@ -1,6 +1,7 @@
<?php
declare( strict_types=1 );
+use Automattic\WooCommerce\Admin\API\Reports\Customers\Controller as CustomersController;
use Automattic\WooCommerce\Admin\API\Reports\Customers\DataStore as CustomersDataStore;
use Automattic\WooCommerce\Enums\OrderStatus;
@@ -639,4 +640,343 @@ class WC_Admin_Reports_Customers_Controller_Test extends WC_REST_Unit_Test_Case
$this->assertNotEquals( 'CA', $report['state'], 'No customers should be from CA state' );
}
}
+
+ /**
+ * Test email_includes filters by email column.
+ */
+ public function test_email_includes() {
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'email_includes' => 'customer1@example.com',
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $this->assertCount( 1, $reports, 'Should return 1 customer matching the email' );
+ $this->assertEquals( 'customer1@example.com', $reports[0]['email'], 'Returned customer should have the matching email' );
+ }
+
+ /**
+ * Test email_excludes filters by email column.
+ */
+ public function test_email_excludes() {
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'email_excludes' => 'customer1@example.com,customer2@example.com,customer3@example.com',
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $this->assertCount( 2, $reports, 'Should return 2 guest customers after excluding all registered customer emails' );
+ $emails = array_column( $reports, 'email' );
+ $this->assertNotContains( 'customer1@example.com', $emails, 'Excluded email should not appear' );
+ $this->assertNotContains( 'customer2@example.com', $emails, 'Excluded email should not appear' );
+ $this->assertNotContains( 'customer3@example.com', $emails, 'Excluded email should not appear' );
+ }
+
+ /**
+ * Test username_includes filters by username column.
+ */
+ public function test_username_includes() {
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'username_includes' => 'customer1',
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $this->assertCount( 1, $reports, 'Should return 1 customer matching the username' );
+ $this->assertEquals( 'customer1', $reports[0]['username'], 'Returned customer should have the matching username' );
+ }
+
+ /**
+ * Test username_excludes filters by username column.
+ */
+ public function test_username_excludes() {
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'username_excludes' => 'customer1,customer2',
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $usernames = array_column( $reports, 'username' );
+ $this->assertNotContains( 'customer1', $usernames, 'Excluded username should not appear' );
+ $this->assertNotContains( 'customer2', $usernames, 'Excluded username should not appear' );
+ $this->assertGreaterThanOrEqual( 3, count( $reports ), 'Should return at least 3 customers (customer3 + 2 guests)' );
+ }
+
+ /**
+ * Test name_includes filters by name column.
+ */
+ public function test_name_includes() {
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'name_includes' => 'John Doe',
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $this->assertCount( 1, $reports, 'Should return 1 customer matching the name' );
+ $this->assertEquals( 'John Doe', $reports[0]['name'], 'Returned customer should have the matching name' );
+ }
+
+ /**
+ * Test name_excludes filters by name column.
+ */
+ public function test_name_excludes() {
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'name_excludes' => 'John Doe,Jane Smith',
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $names = array_column( $reports, 'name' );
+ $this->assertNotContains( 'John Doe', $names, 'Excluded name should not appear' );
+ $this->assertNotContains( 'Jane Smith', $names, 'Excluded name should not appear' );
+ $this->assertGreaterThanOrEqual( 3, count( $reports ), 'Should return at least 3 customers (Bob Johnson + 2 guests)' );
+ }
+
+ /**
+ * Test country_includes filters by country column.
+ */
+ public function test_country_includes() {
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'country_includes' => 'CA',
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $this->assertCount( 1, $reports, 'Should return 1 customer from CA' );
+ $this->assertEquals( 'CA', $reports[0]['country'], 'Returned customer should be from CA' );
+ }
+
+ /**
+ * Test country_excludes filters by country column.
+ */
+ public function test_country_excludes() {
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'country_excludes' => 'US',
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $this->assertCount( 1, $reports, 'Should return 1 customer not from US' );
+ $this->assertEquals( 'CA', $reports[0]['country'], 'Returned customer should be from CA' );
+ }
+
+ /**
+ * @testdox Should consolidate numeric name_includes IDs into customers param.
+ */
+ public function test_name_includes_with_customer_ids(): void {
+ $customer_id = CustomersDataStore::get_customer_id_by_user_id( $this->registered_customers[0]->get_id() );
+
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'name_includes' => (string) $customer_id,
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $this->assertCount( 1, $reports, 'Should return 1 customer matching the customer ID' );
+ $this->assertEquals( 'John Doe', $reports[0]['name'], 'Returned customer should be John Doe' );
+ }
+
+ /**
+ * @testdox Should consolidate numeric email_includes IDs into customers param.
+ */
+ public function test_email_includes_with_customer_ids(): void {
+ $customer_id_1 = CustomersDataStore::get_customer_id_by_user_id( $this->registered_customers[0]->get_id() );
+ $customer_id_2 = CustomersDataStore::get_customer_id_by_user_id( $this->registered_customers[1]->get_id() );
+
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'email_includes' => "{$customer_id_1},{$customer_id_2}",
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $this->assertCount( 2, $reports, 'Should return 2 customers matching the customer IDs' );
+ }
+
+ /**
+ * @testdox Should filter by customers_exclude param.
+ */
+ public function test_customers_exclude(): void {
+ $customer_id_1 = CustomersDataStore::get_customer_id_by_user_id( $this->registered_customers[0]->get_id() );
+ $customer_id_2 = CustomersDataStore::get_customer_id_by_user_id( $this->registered_customers[1]->get_id() );
+
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'customers_exclude' => array( $customer_id_1, $customer_id_2 ),
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $ids = array_column( $reports, 'id' );
+ $this->assertNotContains( $customer_id_1, $ids, 'Excluded customer ID should not appear' );
+ $this->assertNotContains( $customer_id_2, $ids, 'Excluded customer ID should not appear' );
+ }
+
+ /**
+ * @testdox Should consolidate numeric exclude IDs into customers_exclude param.
+ */
+ public function test_email_excludes_with_customer_ids(): void {
+ $customer_id = CustomersDataStore::get_customer_id_by_user_id( $this->registered_customers[0]->get_id() );
+
+ $request = new WP_REST_Request( 'GET', $this->endpoint );
+ $request->set_query_params(
+ array(
+ 'email_excludes' => (string) $customer_id,
+ )
+ );
+
+ $response = $this->server->dispatch( $request );
+ $reports = $response->get_data();
+
+ $this->assertEquals( 200, $response->get_status() );
+ $ids = array_column( $reports, 'id' );
+ $this->assertNotContains( $customer_id, $ids, 'Customer excluded by ID should not appear' );
+ }
+
+ /**
+ * @testdox Should intersect include sets when match=all.
+ */
+ public function test_consolidation_match_all_intersection(): void {
+ $customer_id_1 = CustomersDataStore::get_customer_id_by_user_id( $this->registered_customers[0]->get_id() );
+ $customer_id_2 = CustomersDataStore::get_customer_id_by_user_id( $this->registered_customers[1]->get_id() );
+
+ $args = CustomersController::consolidate_customer_id_filters(
+ array(
+ 'match' => 'all',
+ 'name_includes' => "{$customer_id_1},{$customer_id_2}",
+ 'email_includes' => (string) $customer_id_1,
+ 'username_includes' => null,
+ 'name_excludes' => null,
+ 'email_excludes' => null,
+ 'username_excludes' => null,
+ )
+ );
+
+ $this->assertEquals( array( $customer_id_1 ), $args['customers'], 'match=all should intersect include sets' );
+ $this->assertNull( $args['name_includes'], 'Consolidated param should be nulled' );
+ $this->assertNull( $args['email_includes'], 'Consolidated param should be nulled' );
+ }
+
+ /**
+ * @testdox Should union include sets when match=any.
+ */
+ public function test_consolidation_match_any_union(): void {
+ $customer_id_1 = CustomersDataStore::get_customer_id_by_user_id( $this->registered_customers[0]->get_id() );
+ $customer_id_2 = CustomersDataStore::get_customer_id_by_user_id( $this->registered_customers[1]->get_id() );
+
+ $args = CustomersController::consolidate_customer_id_filters(
+ array(
+ 'match' => 'any',
+ 'name_includes' => (string) $customer_id_1,
+ 'email_includes' => (string) $customer_id_2,
+ 'username_includes' => null,
+ 'name_excludes' => null,
+ 'email_excludes' => null,
+ 'username_excludes' => null,
+ )
+ );
+
+ $customers = $args['customers'];
+ sort( $customers );
+ $expected = array( $customer_id_1, $customer_id_2 );
+ sort( $expected );
+ $this->assertEquals( $expected, $customers, 'match=any should union include sets' );
+ }
+
+ /**
+ * @testdox Should union exclude sets when match=all.
+ */
+ public function test_consolidation_excludes_match_all(): void {
+ $args = CustomersController::consolidate_customer_id_filters(
+ array(
+ 'match' => 'all',
+ 'name_includes' => null,
+ 'email_includes' => null,
+ 'username_includes' => null,
+ 'name_excludes' => '1,2',
+ 'email_excludes' => '2,3',
+ 'username_excludes' => null,
+ )
+ );
+
+ $excluded = $args['customers_exclude'];
+ sort( $excluded );
+ $this->assertEquals( array( 1, 2, 3 ), $excluded, 'match=all should union exclude sets' );
+ }
+
+ /**
+ * @testdox Should not consolidate non-numeric string values.
+ */
+ public function test_string_values_not_consolidated(): void {
+ $args = CustomersController::consolidate_customer_id_filters(
+ array(
+ 'match' => 'all',
+ 'name_includes' => 'John Doe',
+ 'email_includes' => 'customer1@example.com',
+ 'username_includes' => null,
+ 'name_excludes' => 'Jane Smith',
+ 'email_excludes' => null,
+ 'username_excludes' => null,
+ )
+ );
+
+ $this->assertEquals( 'John Doe', $args['name_includes'], 'String name should not be consolidated' );
+ $this->assertEquals( 'customer1@example.com', $args['email_includes'], 'String email should not be consolidated' );
+ $this->assertEquals( 'Jane Smith', $args['name_excludes'], 'String name_excludes should not be consolidated' );
+ $this->assertArrayNotHasKey( 'customers', $args, 'customers should not be set for non-numeric values' );
+ $this->assertArrayNotHasKey( 'customers_exclude', $args, 'customers_exclude should not be set for non-numeric values' );
+ }
}