Merge pull request woocommerce/woocommerce-admin#1260 from woocommerce/fix/1239-handle-between-rest-api-param

Handle *_between params in Reports controllers
This commit is contained in:
Jeff Stieler 2019-01-10 10:52:08 -07:00 committed by GitHub
commit adf8bbeb23
3 changed files with 141 additions and 30 deletions

View File

@ -38,31 +38,33 @@ class WC_Admin_REST_Reports_Customers_Controller extends WC_REST_Reports_Control
* @return array
*/
protected function prepare_reports_query( $request ) {
$args = array();
$args['registered_before'] = $request['registered_before'];
$args['registered_after'] = $request['registered_after'];
$args['page'] = $request['page'];
$args['per_page'] = $request['per_page'];
$args['order'] = $request['order'];
$args['orderby'] = $request['orderby'];
$args['match'] = $request['match'];
$args['name'] = $request['name'];
$args['username'] = $request['username'];
$args['email'] = $request['email'];
$args['country'] = $request['country'];
$args['last_active_before'] = $request['last_active_before'];
$args['last_active_after'] = $request['last_active_after'];
$args['orders_count_min'] = $request['orders_count_min'];
$args['orders_count_max'] = $request['orders_count_max'];
$args['orders_count_between'] = $request['orders_count_between'];
$args['total_spend_min'] = $request['total_spend_min'];
$args['total_spend_max'] = $request['total_spend_max'];
$args['total_spend_between'] = $request['total_spend_between'];
$args['avg_order_value_min'] = $request['avg_order_value_min'];
$args['avg_order_value_max'] = $request['avg_order_value_max'];
$args['avg_order_value_between'] = $request['avg_order_value_between'];
$args['last_order_before'] = $request['last_order_before'];
$args['last_order_after'] = $request['last_order_after'];
$args = array();
$args['registered_before'] = $request['registered_before'];
$args['registered_after'] = $request['registered_after'];
$args['page'] = $request['page'];
$args['per_page'] = $request['per_page'];
$args['order'] = $request['order'];
$args['orderby'] = $request['orderby'];
$args['match'] = $request['match'];
$args['name'] = $request['name'];
$args['username'] = $request['username'];
$args['email'] = $request['email'];
$args['country'] = $request['country'];
$args['last_active_before'] = $request['last_active_before'];
$args['last_active_after'] = $request['last_active_after'];
$args['orders_count_min'] = $request['orders_count_min'];
$args['orders_count_max'] = $request['orders_count_max'];
$args['total_spend_min'] = $request['total_spend_min'];
$args['total_spend_max'] = $request['total_spend_max'];
$args['avg_order_value_min'] = $request['avg_order_value_min'];
$args['avg_order_value_max'] = $request['avg_order_value_max'];
$args['last_order_before'] = $request['last_order_before'];
$args['last_order_after'] = $request['last_order_after'];
$between_params = array( 'orders_count', 'total_spend', 'avg_order_value' );
$normalized = WC_Admin_Reports_Interval::normalize_between_params( $request, $between_params );
$args = array_merge( $args, $normalized );
return $args;
}
@ -388,7 +390,7 @@ class WC_Admin_REST_Reports_Customers_Controller extends WC_REST_Reports_Control
$params['orders_count_between'] = array(
'description' => __( 'Limit response to objects with an order count between two given integers.', 'wc-admin' ),
'type' => 'array',
'validate_callback' => 'rest_validate_request_arg',
'validate_callback' => array( 'WC_Admin_Reports_Interval', 'rest_validate_between_arg' ),
);
$params['total_spend_min'] = array(
'description' => __( 'Limit response to objects with a total order spend greater than or equal to given number.', 'wc-admin' ),
@ -403,7 +405,7 @@ class WC_Admin_REST_Reports_Customers_Controller extends WC_REST_Reports_Control
$params['total_spend_between'] = array(
'description' => __( 'Limit response to objects with a total order spend between two given numbers.', 'wc-admin' ),
'type' => 'array',
'validate_callback' => 'rest_validate_request_arg',
'validate_callback' => array( 'WC_Admin_Reports_Interval', 'rest_validate_between_arg' ),
);
$params['avg_order_value_min'] = array(
'description' => __( 'Limit response to objects with an average order spend greater than or equal to given number.', 'wc-admin' ),
@ -418,7 +420,7 @@ class WC_Admin_REST_Reports_Customers_Controller extends WC_REST_Reports_Control
$params['avg_order_value_between'] = array(
'description' => __( 'Limit response to objects with an average order spend between two given numbers.', 'wc-admin' ),
'type' => 'array',
'validate_callback' => 'rest_validate_request_arg',
'validate_callback' => array( 'WC_Admin_Reports_Interval', 'rest_validate_between_arg' ),
);
$params['last_order_before'] = array(
'description' => __( 'Limit response to objects with last order before (or at) a given ISO8601 compliant datetime.', 'wc-admin' ),

View File

@ -1,6 +1,6 @@
<?php
/**
* Class for time interval handling for reports
* Class for time interval and numeric range handling for reports.
*
* @package WooCommerce Admin/Classes
*/
@ -8,7 +8,7 @@
defined( 'ABSPATH' ) || exit;
/**
* Date & time interval handling class for Reporting API.
* Date & time interval and numeric range handling class for Reporting API.
*/
class WC_Admin_Reports_Interval {
@ -474,4 +474,72 @@ class WC_Admin_Reports_Interval {
}
}
/**
* Normalize "*_between" parameters to "*_min" and "*_max".
*
* @param array $request Query params from REST API request.
* @param string|array $param_names One or more param names to handle. Should not include "_between" suffix.
* @return array Normalized query values.
*/
public static function normalize_between_params( $request, $param_names ) {
if ( ! is_array( $param_names ) ) {
$param_names = array( $param_names );
}
$normalized = array();
foreach ( $param_names as $param_name ) {
if ( ! is_array( $request[ $param_name . '_between' ] ) ) {
continue;
}
$range = $request[ $param_name . '_between' ];
if ( 2 !== count( $range ) ) {
continue;
}
if ( $range[0] < $range[1] ) {
$normalized[ $param_name . '_min' ] = $range[0];
$normalized[ $param_name . '_max' ] = $range[1];
} else {
$normalized[ $param_name . '_min' ] = $range[1];
$normalized[ $param_name . '_max' ] = $range[0];
}
}
return $normalized;
}
/**
* Validate a "*_between" range argument (an array with 2 numeric items).
*
* @param mixed $value Parameter value.
* @param WP_REST_Request $request REST Request.
* @param string $param Parameter name.
* @return WP_Error|boolean
*/
public static function rest_validate_between_arg( $value, $request, $param ) {
if ( ! wp_is_numeric_array( $value ) ) {
return new WP_Error(
'rest_invalid_param',
/* translators: 1: parameter name */
sprintf( __( '%1$s is not a numerically indexed array.', 'wc-admin' ), $param )
);
}
if (
2 !== count( $value ) ||
! is_numeric( $value[0] ) ||
! is_numeric( $value[1] )
) {
return new WP_Error(
'rest_invalid_param',
/* translators: %s: parameter name */
sprintf( __( '%s must contain 2 numbers.', 'wc-admin' ), $param )
);
}
return true;
}
}

View File

@ -796,4 +796,45 @@ class WC_Tests_Reports_Interval_Stats extends WC_Unit_Test_Case {
}
}
/**
* Test function that normalizes *_between query parameters to *_min & *_max.
*/
public function test_normalize_between_params() {
$request = array(
'a_between' => 'malformed', // won't be normalized (not an array).
'b_between' => array( 1, 5 ), // results in min=1, max=5.
'c_between' => array( 4, 2 ), // results in min=2, max=4.
'd_between' => array( 7 ), // won't be normalized (only 1 item).
'f_between' => array( 10, 12 ), // not in params, skipped.
);
$params = array( 'a', 'b', 'c', 'd' );
$result = WC_Admin_Reports_Interval::normalize_between_params( $request, $params );
$expected = array(
'b_min' => 1,
'b_max' => 5,
'c_min' => 2,
'c_max' => 4,
);
$this->assertEquals( $result, $expected );
}
/**
* Test function that validates *_between query parameters.
*/
public function test_rest_validate_between_arg() {
$this->assertIsWPError(
WC_Admin_Reports_Interval::rest_validate_between_arg( 'not array', null, 'param' ),
'param is not a numerically indexed array.'
);
$this->assertIsWPError(
WC_Admin_Reports_Interval::rest_validate_between_arg( array( 1 ), null, 'param' ),
'param must contain 2 numbers.'
);
$this->assertTrue(
WC_Admin_Reports_Interval::rest_validate_between_arg( array( 1, 2 ), null, 'param' )
);
}
}