It's not easy, but a colleague and I did it.
Some of this is specific to our use case, and it will not be very performant on larger catalogues, but it technically works. As there's not way of telling if this is the case before fetching the items, we display all items on a page and simply display:none on the out of stock items. Again, this is a workaround but works for our purposes.
function product_in_stock($post, $product) {
if ($_GET['filtering'] == 1 && $_GET['filter_size'] > 0 ) {
$STOCK = FALSE;
$slugmap = array();
$attribs = $product->get_variation_attributes();
$terms = get_terms( sanitize_title( 'pa_size' ));
if($terms)foreach($terms as $term)$slugmap[$term->slug]=$term->term_id;
$available = $product->get_available_variations();
if($available)foreach($available as $instockitem){
if(isset($instockitem["attributes"]["attribute_pa_size"])){
if(isset($slugmap[$instockitem["attributes"]["attribute_pa_size"]])){
if($slugmap[$instockitem["attributes"]["attribute_pa_size"]] == $_GET["filter_size"]){
$STOCK = TRUE;
}
}
}
}
return $STOCK;
} else {
return true;
}
}
function check_if_out_of_stock(){
global $post,$product;
$stock = product_in_stock($post,$product);
$output = '<div class="';
$output .= $stock?"instock":"outofstock";
$output .= '">';
echo $output;
}
add_action( 'woocommerce_before_shop_loop_item', 'check_if_out_of_stock');
function close_out_of_stock(){
echo "</div>";
}
add_action( 'woocommerce_after_shop_loop_item', 'close_out_of_stock');