[WC Analytics] Add filters for custom orderby query params (#49722)

* Add a filter `woocommerce_report_categories_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_coupons_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_coupons_stats_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_customers_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_downloads_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_downloads_stats_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_orders_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_orders_stats_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_products_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_products_stats_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_revenue_stats_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_stock_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_taxes_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_taxes_stats_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_variations_orderby_params` for custom orderby query params

* Add a filter `woocommerce_report_variations_stats_orderby_params` for custom orderby query params

* Add changelog

* Add a method `apply_custom_orderby_filters()` in analytics GenericController

* Use the shared method to in analytics GenericController to apply custom
orderby enum

* Fix typo, add more comments in analytics custom orderby filter PHPDoc

---------

Co-authored-by: Tomek Wytrębowicz <tomalecpub@gmail.com>
This commit is contained in:
Ian Yu-Hsun Lin 2024-09-06 12:13:03 +08:00 committed by GitHub
parent cb2549386a
commit 43ce3c1c4d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 175 additions and 112 deletions

View File

@ -0,0 +1,4 @@
Significance: minor
Type: enhancement
Add filters for custom orderby query params for WC Analytics

View File

@ -171,13 +171,15 @@ class Controller extends GenericController implements ExportableInterface {
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['default'] = 'category_id'; $params['orderby']['default'] = 'category_id';
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'category_id', 'category_id',
'items_sold', 'items_sold',
'net_revenue', 'net_revenue',
'orders_count', 'orders_count',
'products_count', 'products_count',
'category', 'category',
)
); );
$params['interval'] = array( $params['interval'] = array(
'description' => __( 'Time interval to use for buckets in the returned data.', 'woocommerce' ), 'description' => __( 'Time interval to use for buckets in the returned data.', 'woocommerce' ),

View File

@ -184,11 +184,13 @@ class Controller extends GenericController implements ExportableInterface {
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['default'] = 'coupon_id'; $params['orderby']['default'] = 'coupon_id';
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'coupon_id', 'coupon_id',
'code', 'code',
'amount', 'amount',
'orders_count', 'orders_count',
)
); );
$params['coupons'] = array( $params['coupons'] = array(
'description' => __( 'Limit result set to coupons assigned specific coupon IDs.', 'woocommerce' ), 'description' => __( 'Limit result set to coupons assigned specific coupon IDs.', 'woocommerce' ),

View File

@ -142,11 +142,13 @@ class Controller extends GenericStatsController {
*/ */
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'amount', 'amount',
'coupons_count', 'coupons_count',
'orders_count', 'orders_count',
)
); );
$params['coupons'] = array( $params['coupons'] = array(
'description' => __( 'Limit result set to coupons assigned specific coupon IDs.', 'woocommerce' ), 'description' => __( 'Limit result set to coupons assigned specific coupon IDs.', 'woocommerce' ),

View File

@ -304,7 +304,8 @@ class Controller extends GenericController implements ExportableInterface {
'validate_callback' => 'rest_validate_request_arg', 'validate_callback' => 'rest_validate_request_arg',
); );
$params['orderby']['default'] = 'date_registered'; $params['orderby']['default'] = 'date_registered';
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'username', 'username',
'name', 'name',
'country', 'country',
@ -316,6 +317,7 @@ class Controller extends GenericController implements ExportableInterface {
'orders_count', 'orders_count',
'total_spend', 'total_spend',
'avg_order_value', 'avg_order_value',
)
); );
$params['match'] = array( $params['match'] = array(
'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: status_is, status_is_not, product_includes, product_excludes, coupon_includes, coupon_excludes, customer, categories', 'woocommerce' ), 'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: status_is, status_is_not, product_includes, product_excludes, coupon_includes, coupon_excludes, customer, categories', 'woocommerce' ),

View File

@ -219,9 +219,11 @@ class Controller extends GenericController implements ExportableInterface {
*/ */
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'product', 'product',
)
); );
$params['match'] = array( $params['match'] = array(
'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: products, orders, username, ip_address.', 'woocommerce' ), 'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: products, orders, username, ip_address.', 'woocommerce' ),

View File

@ -196,9 +196,11 @@ class Controller extends GenericStatsController {
*/ */
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'download_count', 'download_count',
)
); );
$params['match'] = array( $params['match'] = array(
'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: status_is, status_is_not, product_includes, product_excludes, coupon_includes, coupon_excludes, customer, categories', 'woocommerce' ), 'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: status_is, status_is_not, product_includes, product_excludes, coupon_includes, coupon_excludes, customer, categories', 'woocommerce' ),

View File

@ -257,4 +257,31 @@ abstract class GenericController extends \WC_REST_Reports_Controller {
return $args; return $args;
} }
/**
* Apply a filter for custom orderby enum.
*
* @param array $orderby_enum An array of orderby enum options.
*
* @return array An array of filtered orderby enum options.
*
* @since 9.4.0
*/
protected function apply_custom_orderby_filters( $orderby_enum ) {
/**
* Filter orderby query parameter enum.
*
* There was an initial concern about potential SQL injection with the custom orderby.
* However, testing shows it is safely blocked by validation in the controller,
* which results in an "Invalid parameter(s): orderby" error.
*
* Additionally, it's the responsibility of the merchant/developer to ensure the custom orderby is valid,
* or a WordPress database error will occur for unknown columns.
*
* @since 9.4.0
*
* @param array $orderby_enum The orderby query parameter enum.
*/
return apply_filters( "woocommerce_analytics_orderby_enum_{$this->rest_base}", $orderby_enum );
}
} }

View File

@ -233,10 +233,12 @@ class Controller extends GenericController implements ExportableInterface {
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['per_page']['minimum'] = 0; $params['per_page']['minimum'] = 0;
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'num_items_sold', 'num_items_sold',
'net_total', 'net_total',
)
); );
$params['product_includes'] = array( $params['product_includes'] = array(
'description' => __( 'Limit result set to items that have the specified product(s) assigned.', 'woocommerce' ), 'description' => __( 'Limit result set to items that have the specified product(s) assigned.', 'woocommerce' ),

View File

@ -202,11 +202,13 @@ class Controller extends GenericStatsController {
*/ */
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'net_revenue', 'net_revenue',
'orders_count', 'orders_count',
'avg_order_value', 'avg_order_value',
)
); );
$params['match'] = array( $params['match'] = array(
'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: status_is, status_is_not, product_includes, product_excludes, coupon_includes, coupon_excludes, customer, categories', 'woocommerce' ), 'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: status_is, status_is_not, product_includes, product_excludes, coupon_includes, coupon_excludes, customer, categories', 'woocommerce' ),

View File

@ -231,7 +231,8 @@ class Controller extends GenericController implements ExportableInterface {
*/ */
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'net_revenue', 'net_revenue',
'orders_count', 'orders_count',
@ -239,6 +240,7 @@ class Controller extends GenericController implements ExportableInterface {
'product_name', 'product_name',
'variations', 'variations',
'sku', 'sku',
)
); );
$params['categories'] = array( $params['categories'] = array(
'description' => __( 'Limit result to items from the specified categories.', 'woocommerce' ), 'description' => __( 'Limit result to items from the specified categories.', 'woocommerce' ),

View File

@ -197,7 +197,8 @@ class Controller extends GenericStatsController {
*/ */
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'net_revenue', 'net_revenue',
'coupons', 'coupons',
@ -207,6 +208,7 @@ class Controller extends GenericStatsController {
'net_revenue', 'net_revenue',
'orders_count', 'orders_count',
'items_sold', 'items_sold',
)
); );
$params['categories'] = array( $params['categories'] = array(
'description' => __( 'Limit result to items from the specified categories.', 'woocommerce' ), 'description' => __( 'Limit result to items from the specified categories.', 'woocommerce' ),

View File

@ -223,7 +223,8 @@ class Controller extends GenericStatsController implements ExportableInterface {
*/ */
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'total_sales', 'total_sales',
'coupons', 'coupons',
@ -234,6 +235,7 @@ class Controller extends GenericStatsController implements ExportableInterface {
'orders_count', 'orders_count',
'items_sold', 'items_sold',
'gross_sales', 'gross_sales',
)
); );
$params['segmentby'] = array( $params['segmentby'] = array(
'description' => __( 'Segment the response by additional constraint.', 'woocommerce' ), 'description' => __( 'Segment the response by additional constraint.', 'woocommerce' ),

View File

@ -443,7 +443,8 @@ class Controller extends GenericController implements ExportableInterface {
); );
$params['order']['default'] = 'asc'; $params['order']['default'] = 'asc';
$params['orderby']['default'] = 'stock_status'; $params['orderby']['default'] = 'stock_status';
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'stock_status', 'stock_status',
'stock_quantity', 'stock_quantity',
'date', 'date',
@ -451,6 +452,7 @@ class Controller extends GenericController implements ExportableInterface {
'include', 'include',
'title', 'title',
'sku', 'sku',
)
); );
$params['parent'] = array( $params['parent'] = array(
'description' => __( 'Limit result set to those of particular parent IDs.', 'woocommerce' ), 'description' => __( 'Limit result set to those of particular parent IDs.', 'woocommerce' ),

View File

@ -195,7 +195,8 @@ class Controller extends GenericController implements ExportableInterface {
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['default'] = 'tax_rate_id'; $params['orderby']['default'] = 'tax_rate_id';
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'name', 'name',
'tax_rate_id', 'tax_rate_id',
'tax_code', 'tax_code',
@ -204,6 +205,7 @@ class Controller extends GenericController implements ExportableInterface {
'total_tax', 'total_tax',
'shipping_tax', 'shipping_tax',
'orders_count', 'orders_count',
)
); );
$params['taxes'] = array( $params['taxes'] = array(
'description' => __( 'Limit result set to items assigned one or more tax rates.', 'woocommerce' ), 'description' => __( 'Limit result set to items assigned one or more tax rates.', 'woocommerce' ),

View File

@ -186,12 +186,14 @@ class Controller extends GenericStatsController {
*/ */
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'items_sold', 'items_sold',
'total_sales', 'total_sales',
'orders_count', 'orders_count',
'products_count', 'products_count',
)
); );
$params['taxes'] = array( $params['taxes'] = array(
'description' => __( 'Limit result set to all items that have the specified term assigned in the taxes taxonomy.', 'woocommerce' ), 'description' => __( 'Limit result set to all items that have the specified term assigned in the taxes taxonomy.', 'woocommerce' ),

View File

@ -246,12 +246,14 @@ class Controller extends GenericController implements ExportableInterface {
*/ */
public function get_collection_params() { public function get_collection_params() {
$params = parent::get_collection_params(); $params = parent::get_collection_params();
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'net_revenue', 'net_revenue',
'orders_count', 'orders_count',
'items_sold', 'items_sold',
'sku', 'sku',
)
); );
$params['match'] = array( $params['match'] = array(
'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: status_is, status_is_not, product_includes, product_excludes, coupon_includes, coupon_excludes, customer, categories', 'woocommerce' ), 'description' => __( 'Indicates whether all the conditions should be true for the resulting set, or if any one of them is sufficient. Match affects the following parameters: status_is, status_is_not, product_includes, product_excludes, coupon_includes, coupon_excludes, customer, categories', 'woocommerce' ),

View File

@ -210,7 +210,8 @@ class Controller extends GenericStatsController {
), ),
'validate_callback' => 'rest_validate_request_arg', 'validate_callback' => 'rest_validate_request_arg',
); );
$params['orderby']['enum'] = array( $params['orderby']['enum'] = $this->apply_custom_orderby_filters(
array(
'date', 'date',
'net_revenue', 'net_revenue',
'coupons', 'coupons',
@ -220,6 +221,7 @@ class Controller extends GenericStatsController {
'net_revenue', 'net_revenue',
'orders_count', 'orders_count',
'items_sold', 'items_sold',
)
); );
$params['category_includes'] = array( $params['category_includes'] = array(
'description' => __( 'Limit result to items from the specified categories.', 'woocommerce' ), 'description' => __( 'Limit result to items from the specified categories.', 'woocommerce' ),