diff --git a/plugins/woocommerce-admin/includes/api/class-wc-admin-rest-reports-customers-controller.php b/plugins/woocommerce-admin/includes/api/class-wc-admin-rest-reports-customers-controller.php index 529665852cc..8e1d70b7ce7 100644 --- a/plugins/woocommerce-admin/includes/api/class-wc-admin-rest-reports-customers-controller.php +++ b/plugins/woocommerce-admin/includes/api/class-wc-admin-rest-reports-customers-controller.php @@ -48,9 +48,14 @@ class WC_Admin_REST_Reports_Customers_Controller extends WC_REST_Reports_Control $args['match'] = $request['match']; $args['search'] = $request['search']; $args['searchby'] = $request['searchby']; - $args['username'] = $request['username']; - $args['email'] = $request['email']; - $args['country'] = $request['country']; + $args['name_includes'] = $request['name_includes']; + $args['name_excludes'] = $request['name_excludes']; + $args['username_includes'] = $request['username_includes']; + $args['username_excludes'] = $request['username_excludes']; + $args['email_includes'] = $request['email_includes']; + $args['email_excludes'] = $request['email_excludes']; + $args['country_includes'] = $request['country_includes']; + $args['country_excludes'] = $request['country_excludes']; $args['last_active_before'] = $request['last_active_before']; $args['last_active_after'] = $request['last_active_after']; $args['orders_count_min'] = $request['orders_count_min']; @@ -350,18 +355,43 @@ class WC_Admin_REST_Reports_Customers_Controller extends WC_REST_Reports_Control 'email', ), ); - $params['username'] = array( - 'description' => __( 'Limit response to objects with a specfic username.', 'woocommerce-admin' ), + $params['name_includes'] = array( + 'description' => __( 'Limit response to objects with specfic names.', 'woocommerce-admin' ), 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg', ); - $params['email'] = array( - 'description' => __( 'Limit response to objects equal to an email.', 'woocommerce-admin' ), + $params['name_excludes'] = array( + 'description' => __( 'Limit response to objects excluding specfic names.', 'woocommerce-admin' ), 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg', ); - $params['country'] = array( - 'description' => __( 'Limit response to objects with a specfic country.', 'woocommerce-admin' ), + $params['username_includes'] = array( + 'description' => __( 'Limit response to objects with specfic usernames.', 'woocommerce-admin' ), + 'type' => 'string', + 'validate_callback' => 'rest_validate_request_arg', + ); + $params['username_excludes'] = array( + 'description' => __( 'Limit response to objects excluding specfic usernames.', 'woocommerce-admin' ), + 'type' => 'string', + 'validate_callback' => 'rest_validate_request_arg', + ); + $params['email_includes'] = array( + 'description' => __( 'Limit response to objects including emails.', 'woocommerce-admin' ), + 'type' => 'string', + 'validate_callback' => 'rest_validate_request_arg', + ); + $params['email_excludes'] = array( + 'description' => __( 'Limit response to objects excluding emails.', 'woocommerce-admin' ), + 'type' => 'string', + 'validate_callback' => 'rest_validate_request_arg', + ); + $params['country_includes'] = array( + 'description' => __( 'Limit response to objects with specfic countries.', 'woocommerce-admin' ), + 'type' => 'string', + 'validate_callback' => 'rest_validate_request_arg', + ); + $params['country_excludes'] = array( + 'description' => __( 'Limit response to objects excluding specfic countries.', 'woocommerce-admin' ), 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg', ); diff --git a/plugins/woocommerce-admin/includes/api/class-wc-admin-rest-reports-customers-stats-controller.php b/plugins/woocommerce-admin/includes/api/class-wc-admin-rest-reports-customers-stats-controller.php index f9b98237332..ea7c9aecc05 100644 --- a/plugins/woocommerce-admin/includes/api/class-wc-admin-rest-reports-customers-stats-controller.php +++ b/plugins/woocommerce-admin/includes/api/class-wc-admin-rest-reports-customers-stats-controller.php @@ -42,9 +42,14 @@ class WC_Admin_REST_Reports_Customers_Stats_Controller extends WC_REST_Reports_C $args['registered_after'] = $request['registered_after']; $args['match'] = $request['match']; $args['search'] = $request['search']; - $args['username'] = $request['username']; - $args['email'] = $request['email']; - $args['country'] = $request['country']; + $args['name_includes'] = $request['name_includes']; + $args['name_excludes'] = $request['name_excludes']; + $args['username_includes'] = $request['username_includes']; + $args['username_excludes'] = $request['username_excludes']; + $args['email_includes'] = $request['email_includes']; + $args['email_excludes'] = $request['email_excludes']; + $args['country_includes'] = $request['country_includes']; + $args['country_excludes'] = $request['country_excludes']; $args['last_active_before'] = $request['last_active_before']; $args['last_active_after'] = $request['last_active_after']; $args['orders_count_min'] = $request['orders_count_min']; @@ -211,18 +216,43 @@ class WC_Admin_REST_Reports_Customers_Stats_Controller extends WC_REST_Reports_C 'email', ), ); - $params['username'] = array( - 'description' => __( 'Limit response to objects with a specfic username.', 'woocommerce-admin' ), + $params['name_includes'] = array( + 'description' => __( 'Limit response to objects with specfic names.', 'woocommerce-admin' ), 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg', ); - $params['email'] = array( - 'description' => __( 'Limit response to objects equal to an email.', 'woocommerce-admin' ), + $params['name_excludes'] = array( + 'description' => __( 'Limit response to objects excluding specfic names.', 'woocommerce-admin' ), 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg', ); - $params['country'] = array( - 'description' => __( 'Limit response to objects with a specfic country.', 'woocommerce-admin' ), + $params['username_includes'] = array( + 'description' => __( 'Limit response to objects with specfic usernames.', 'woocommerce-admin' ), + 'type' => 'string', + 'validate_callback' => 'rest_validate_request_arg', + ); + $params['username_excludes'] = array( + 'description' => __( 'Limit response to objects excluding specfic usernames.', 'woocommerce-admin' ), + 'type' => 'string', + 'validate_callback' => 'rest_validate_request_arg', + ); + $params['email_includes'] = array( + 'description' => __( 'Limit response to objects including emails.', 'woocommerce-admin' ), + 'type' => 'string', + 'validate_callback' => 'rest_validate_request_arg', + ); + $params['email_excludes'] = array( + 'description' => __( 'Limit response to objects excluding emails.', 'woocommerce-admin' ), + 'type' => 'string', + 'validate_callback' => 'rest_validate_request_arg', + ); + $params['country_includes'] = array( + 'description' => __( 'Limit response to objects with specfic countries.', 'woocommerce-admin' ), + 'type' => 'string', + 'validate_callback' => 'rest_validate_request_arg', + ); + $params['country_excludes'] = array( + 'description' => __( 'Limit response to objects excluding specfic countries.', 'woocommerce-admin' ), 'type' => 'string', 'validate_callback' => 'rest_validate_request_arg', ); diff --git a/plugins/woocommerce-admin/includes/data-stores/class-wc-admin-reports-customers-data-store.php b/plugins/woocommerce-admin/includes/data-stores/class-wc-admin-reports-customers-data-store.php index b3f322ebcdc..177bb06def7 100644 --- a/plugins/woocommerce-admin/includes/data-stores/class-wc-admin-reports-customers-data-store.php +++ b/plugins/woocommerce-admin/includes/data-stores/class-wc-admin-reports-customers-data-store.php @@ -216,17 +216,29 @@ class WC_Admin_Reports_Customers_Data_Store extends WC_Admin_Reports_Data_Store $having_clauses = array(); $exact_match_params = array( + 'name', 'username', 'email', 'country', ); foreach ( $exact_match_params as $exact_match_param ) { - if ( ! empty( $query_args[ $exact_match_param ] ) ) { - $where_clauses[] = $wpdb->prepare( - "{$customer_lookup_table}.{$exact_match_param} = %s", - $query_args[ $exact_match_param ] - ); // WPCS: unprepared SQL ok. + 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}')"; + } + + 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}')"; } } @@ -239,7 +251,7 @@ class WC_Admin_Reports_Customers_Data_Store extends WC_Admin_Reports_Data_Store if ( ! empty( $query_args['search'] ) ) { $name_like = '%' . $wpdb->esc_like( $query_args['search'] ) . '%'; - if ( empty( $query_args['searchby'] ) || 'name' === $query_args['searchby'] || ! in_array( $query_args['searchby'], $search_params ) ) { + if ( empty( $query_args['searchby'] ) || 'name' === $query_args['searchby'] || ! in_array( $query_args['searchby'], $search_params, true ) ) { $searchby = "CONCAT_WS( ' ', first_name, last_name )"; } else { $searchby = $query_args['searchby']; @@ -250,7 +262,7 @@ class WC_Admin_Reports_Customers_Data_Store extends WC_Admin_Reports_Data_Store // Allow a list of customer IDs to be specified. if ( ! empty( $query_args['customers'] ) ) { - $included_customers = implode( ',', $query_args['customers'] ); + $included_customers = implode( ',', array_map( 'intval', $query_args['customers'] ) ); $where_clauses[] = "{$customer_lookup_table}.customer_id IN ({$included_customers})"; }