WooCommerce admin products filter by on sale

I needed the ability to filter the WooCommerce products list within admin by products which where on sale. This was to allow the client to easily find products they have put on offer within certain categories. The below code achieves this.

It does need some work, as it currently ignores the on sale start and end dates, however you should be able to easily modify it for this purpose.

/*
 * Woocommerce Filter by on sale
 */
function custom_woocommerce_filter_by_onsale($output) {
	global $wp_query;
	
	$selected = 0;
	if (isset($_GET['product_sale'])) {
		$selected = (int)$_GET['product_sale'];
	}
	
	$output .= '
		<select id="dropdown_product_sale" name="product_sale">
			<option value="">Filter by sale</option>
			<option selected="selected" value="1">On sale</option>
			<option selected="selected" value="2">Not on sale</option>
		</select>
	';
	
	return $output;
}
add_action('woocommerce_product_filters', 'custom_woocommerce_filter_by_onsale');



/*
 * Woocommerce Filter by on sale where statement
 */
function custom_woocommerce_filter_by_onsale_where_statement($where) {
	global $wp_query, $wpdb;

	if (!is_admin() || $_GET['post_type'] != "product" || !isset($_GET['product_sale']) || $_GET['product_sale'] <= 0) {
		return $where;
	}

	$productsIDs = [];
	if ($_GET['product_sale'] == 1) {
		$querystr = '
			SELECT p.ID
			FROM ' . $wpdb->posts . ' p
			WHERE p.ID IN (
				SELECT post_id FROM ' . $wpdb->postmeta . ' pm WHERE pm.meta_key = "_sale_price" AND pm.meta_value > \'\'
			)
		';
		
		$pageposts = $wpdb->get_results($querystr, OBJECT);
		
		$productsIDs = array_map(function($n){
			return $n->ID;
		}, $pageposts);
	} elseif ($_GET['product_sale'] == 2) {
		$querystr = '
			SELECT p.ID
			FROM ' . $wpdb->posts . ' p
			WHERE p.ID NOT IN (
				SELECT post_id FROM ' . $wpdb->postmeta . ' pm WHERE pm.meta_key = "_sale_price" AND pm.meta_value > \'\'
			)
		';
		
		$pageposts = $wpdb->get_results($querystr, OBJECT);
		
		$productsIDs = array_map(function($n){
			return $n->ID;
		}, $pageposts);
	}
	
	$where .= ' AND ' . $wpdb->posts . '.ID IN (' . implode(",", $productsIDs) . ') ';
	
	return $where;
}
add_filter('posts_where' , 'custom_woocommerce_filter_by_onsale_where_statement');

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments

  1. Jarkko Saltiola

    Thank’s for this, helped a bit.

    There’s a little typo though. Line 32 gives “PHP Parse error: syntax error, unexpected ‘='”.

    So just change “= >” to “=>”.