Last active
July 24, 2022 10:17
-
-
Save RadGH/332a447cdcdd76c84a48148d596ce5e6 to your computer and use it in GitHub Desktop.
Exclude out of stock and hidden products from WooCommerce query with pre_get_posts (plus equivalent filter for Ajax Load More)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* | |
Solution based on a Stack Overflow answer by patrickzdb: | |
https://stackoverflow.com/a/24514985/470480 | |
Tax query solution for hidden products based on a WordPress Stack Exchange answer by kalle: | |
https://wordpress.stackexchange.com/a/262628/19105 | |
Please note: | |
This file includes two functions/filters. | |
The first is for vanilla WordPress pre_get_posts. | |
If you do not use Ajax Load More, just copy the first function + action. | |
The second is specific to Ajax Load More. | |
If you use Ajax Load More, copy both functions + action/filter. | |
*/ | |
/** | |
* WooCommerce by default hides out of stock products AFTER the query. | |
* This leaves gaps: If you have 16 products per page, but 1 of those products are out of stock, you only see 15. | |
* This solution excludes out of stock products during the query, so you'll get the expected results even if some of the products are out of stock. | |
* | |
* @param $query | |
* | |
* @return WP_Query $query | |
*/ | |
function rs_remove_out_of_stock_products_from_query( $query ) { | |
if ( is_admin() ) return $query; | |
// Only affect product archives | |
// Consider using is_main_query(), although I wouldn't want out of stock products on secondary queries either!. | |
if ( !$query->is_post_type_archive('product') ) return $query; | |
// Set up meta query | |
$meta_query = array(); | |
// If a meta_query already exists, keep it -- require those condntions in addition to the stock query | |
if ( !empty($query->get('meta_query')) ) { | |
$meta_query = array( | |
'relation' => 'AND', | |
$query->get('meta_query') | |
); | |
} | |
// Exclude out of stock products | |
$meta_query[] = array( | |
'key' => '_stock_status', | |
'value' => 'outofstock', | |
'compare' => 'NOT IN' | |
); | |
$query->set('meta_query', $meta_query); | |
return $query; | |
} | |
add_action( 'pre_get_posts', 'rs_remove_out_of_stock_products_from_query', 20 ); | |
// AJAX LOAD MORE ONLY: | |
/** | |
* (AJAX LOAD MORE VERSION OF rs_remove_out_of_stock_products_from_query) | |
* | |
* @param $args | |
* | |
* @return array $args | |
*/ | |
function rs_remove_out_of_stock_products_from_alm( $args ) { | |
if ( is_admin() ) return $args; | |
$post_type = false; | |
// Get post type, which may be an array or string. | |
if ( !empty($args['post_type']) ) { | |
if ( is_string($args['post_type']) ) $post_type = $args['post_type']; | |
else if ( is_array($args['post_type']) && count($args['post_type']) == 1 ) $post_type = $args['post_type'][0]; | |
} | |
// Only affect products | |
if ( $post_type !== 'product' ) return $args; | |
// Set up meta query | |
$meta_query = array(); | |
// If a meta_query already exists, keep it -- require those condntions in addition to the stock query | |
if ( !empty($args['meta_query']) ) { | |
$meta_query = array( | |
'relation' => 'AND', | |
$args['meta_query'] | |
); | |
} | |
// Exclude out of stock products | |
$meta_query[] = array( | |
'key' => '_stock_status', | |
'value' => 'outofstock', | |
'compare' => 'NOT IN' | |
); | |
$args['meta_query'] = $meta_query; | |
return $args; | |
} | |
add_filter( 'alm_modify_query_args', 'rs_remove_out_of_stock_products_from_alm', 20 ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Updated to also exclude hidden products, as set in "Catalog Visibility" on the product page