SKU and price sorting using lookup table in admin

This commit is contained in:
Mike Jolley 2019-03-07 13:47:15 +00:00
parent 91aa1b92e5
commit 94b19dc3ca
1 changed files with 157 additions and 75 deletions

View File

@ -39,7 +39,8 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
add_filter( 'query_vars', array( $this, 'add_custom_query_var' ) );
add_filter( 'views_edit-product', array( $this, 'product_views' ) );
add_filter( 'get_search_query', array( $this, 'search_label' ) );
add_filter( 'posts_clauses', array( $this, 'add_variation_parents_for_shipping_class' ), 10, 2 );
add_filter( 'posts_clauses', array( $this, 'posts_clauses' ), 10, 2 );
add_filter( 'the_posts', array( $this, 'remove_ordering_args' ) );
}
/**
@ -383,80 +384,6 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
echo $output; // WPCS: XSS ok.
}
/**
* Handle any custom filters.
*
* @param array $query_vars Query vars.
* @return array
*/
protected function query_filters( $query_vars ) {
if ( isset( $query_vars['orderby'] ) ) {
if ( 'price' === $query_vars['orderby'] ) {
$query_vars = array_merge(
$query_vars,
array(
// phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_key
'meta_key' => '_price',
'orderby' => 'meta_value_num',
)
);
}
if ( 'sku' === $query_vars['orderby'] ) {
$query_vars = array_merge(
$query_vars,
array(
// phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_key
'meta_key' => '_sku',
'orderby' => 'meta_value',
)
);
}
}
if ( isset( $query_vars['product_type'] ) ) {
if ( 'downloadable' === $query_vars['product_type'] ) {
$query_vars['product_type'] = '';
$query_vars['meta_value'] = 'yes'; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_value
$query_vars['meta_key'] = '_downloadable'; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_key
} elseif ( 'virtual' === $query_vars['product_type'] ) {
$query_vars['product_type'] = '';
$query_vars['meta_value'] = 'yes'; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_value
$query_vars['meta_key'] = '_virtual'; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_key
}
}
if ( isset( $_GET['product_shipping_class'] ) && '0' === $_GET['product_shipping_class'] ) { // WPCS: input var ok.
$query_vars['tax_query'][] = array(
'taxonomy' => 'product_shipping_class',
'field' => 'id',
'terms' => get_terms( 'product_shipping_class', array( 'fields' => 'ids' ) ),
'operator' => 'NOT IN',
);
}
if ( ! empty( $_GET['stock_status'] ) ) {
if ( ! isset( $query_vars['meta_query'] ) ) {
$query_vars['meta_query'] = array(); // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_query
}
$query_vars['meta_query'][] = array(
'key' => '_stock_status',
'value' => wc_clean( wp_unslash( $_GET['stock_status'] ) ),
);
}
// Search using CRUD.
if ( ! empty( $query_vars['s'] ) ) {
$data_store = WC_Data_Store::load( 'product' );
$ids = $data_store->search_products( wc_clean( wp_unslash( $query_vars['s'] ) ), '', true, true );
$query_vars['post__in'] = array_merge( $ids, array( 0 ) );
$query_vars['product_search'] = true;
unset( $query_vars['s'] );
}
return $query_vars;
}
/**
* Search by SKU or ID for products.
*
@ -508,6 +435,161 @@ class WC_Admin_List_Table_Products extends WC_Admin_List_Table {
return wc_clean( wp_unslash( $_GET['s'] ) ); // WPCS: input var ok, sanitization ok.
}
/**
* Handle any custom filters.
*
* @param array $query_vars Query vars.
* @return array
*/
protected function query_filters( $query_vars ) {
if ( isset( $query_vars['orderby'] ) ) {
$orderby = strtolower( $query_vars['orderby'] );
$order = isset( $query_vars['order'] ) ? strtoupper( $query_vars['order'] ) : 'DESC';
if ( 'price' === $orderby ) {
$callback = 'DESC' === $order ? 'order_by_price_desc_post_clauses' : 'order_by_price_asc_post_clauses';
add_filter( 'posts_clauses', array( $this, $callback ) );
}
if ( 'sku' === $orderby ) {
$callback = 'DESC' === $order ? 'order_by_sku_desc_post_clauses' : 'order_by_sku_asc_post_clauses';
add_filter( 'posts_clauses', array( $this, $callback ) );
}
}
if ( isset( $query_vars['product_type'] ) ) {
if ( 'downloadable' === $query_vars['product_type'] ) {
$query_vars['product_type'] = '';
$query_vars['meta_value'] = 'yes'; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_value
$query_vars['meta_key'] = '_downloadable'; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_key
} elseif ( 'virtual' === $query_vars['product_type'] ) {
$query_vars['product_type'] = '';
$query_vars['meta_value'] = 'yes'; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_value
$query_vars['meta_key'] = '_virtual'; // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_key
}
}
if ( isset( $_GET['product_shipping_class'] ) && '0' === $_GET['product_shipping_class'] ) { // WPCS: input var ok.
$query_vars['tax_query'][] = array(
'taxonomy' => 'product_shipping_class',
'field' => 'id',
'terms' => get_terms( 'product_shipping_class', array( 'fields' => 'ids' ) ),
'operator' => 'NOT IN',
);
}
if ( ! empty( $_GET['stock_status'] ) ) {
if ( ! isset( $query_vars['meta_query'] ) ) {
$query_vars['meta_query'] = array(); // phpcs:ignore WordPress.VIP.SlowDBQuery.slow_db_query_meta_query
}
$query_vars['meta_query'][] = array(
'key' => '_stock_status',
'value' => wc_clean( wp_unslash( $_GET['stock_status'] ) ),
);
}
// Search using CRUD.
if ( ! empty( $query_vars['s'] ) ) {
$data_store = WC_Data_Store::load( 'product' );
$ids = $data_store->search_products( wc_clean( wp_unslash( $query_vars['s'] ) ), '', true, true );
$query_vars['post__in'] = array_merge( $ids, array( 0 ) );
$query_vars['product_search'] = true;
unset( $query_vars['s'] );
}
return $query_vars;
}
/**
* Undocumented function
*
* @param array $args Array of SELECT statement pieces (from, where, etc).
* @param WP_Query $query WP_Query instance.
* @return array
*/
public function posts_clauses( $args, $query ) {
return $args;
}
/**
* Remove ordering queries.
*
* @param array $posts Posts from WP Query.
* @return array
*/
public function remove_ordering_args( $posts ) {
remove_filter( 'posts_clauses', array( $this, 'order_by_price_asc_post_clauses' ) );
remove_filter( 'posts_clauses', array( $this, 'order_by_price_desc_post_clauses' ) );
remove_filter( 'posts_clauses', array( $this, 'order_by_sku_asc_post_clauses' ) );
remove_filter( 'posts_clauses', array( $this, 'order_by_sku_desc_post_clauses' ) );
return $posts;
}
/**
* Handle numeric price sorting.
*
* @param array $args Query args.
* @return array
*/
public function order_by_price_asc_post_clauses( $args ) {
$args['join'] = $this->append_product_sorting_table_join( $args['join'] );
$args['orderby'] = ' wc_product_meta_lookup.min_price ASC, wc_product_meta_lookup.product_id ASC ';
return $args;
}
/**
* Handle numeric price sorting.
*
* @param array $args Query args.
* @return array
*/
public function order_by_price_desc_post_clauses( $args ) {
$args['join'] = $this->append_product_sorting_table_join( $args['join'] );
$args['orderby'] = ' wc_product_meta_lookup.max_price DESC, wc_product_meta_lookup.product_id DESC ';
return $args;
}
/**
* Handle sku sorting.
*
* @param array $args Query args.
* @return array
*/
public function order_by_sku_asc_post_clauses( $args ) {
$args['join'] = $this->append_product_sorting_table_join( $args['join'] );
$args['orderby'] = ' wc_product_meta_lookup.sku ASC, wc_product_meta_lookup.product_id ASC ';
return $args;
}
/**
* Handle sku sorting.
*
* @param array $args Query args.
* @return array
*/
public function order_by_sku_desc_post_clauses( $args ) {
$args['join'] = $this->append_product_sorting_table_join( $args['join'] );
$args['orderby'] = ' wc_product_meta_lookup.sku DESC, wc_product_meta_lookup.product_id DESC ';
return $args;
}
/**
* Join wc_product_meta_lookup to posts if not already joined.
*
* @param string $sql SQL join.
* @return string
*/
private function append_product_sorting_table_join( $sql ) {
global $wpdb;
if ( ! strstr( $sql, 'wc_product_meta_lookup' ) ) {
$sql .= " LEFT JOIN {$wpdb->wc_product_meta_lookup} wc_product_meta_lookup ON $wpdb->posts.ID = wc_product_meta_lookup.product_id ";
}
return $sql;
}
/**
* Modifies post query so that it includes parent products whose variations have particular shipping class assigned.
*