Okay, so why doesn’t this work:
The Filter you are using is the posts_results
, which is a filter that is applied AFTER the Results are retrieved from the database. Which has the problem that you are describing: Ordering happens on a page-per-page basis.
What you want to do is add an order TO the SQL-Query, so that the order is applied to the complete result and your Locations are retrieved first open, then closed.
The way to do that is to remove the posts_results
filter, and then use the pre_get_posts
action:
function wpse_420312_order_locations_by_open_closed( $query ) {
//First we need to check that this is the "main" query and that we're not on a backend page
if ( $query->is_main_query() && !is_admin() ) {
$post_type = $query->get('post_type');
if ( $post_type === 'location' ) {
//we need to build a meta query. To learn more, look here: https://developer.wordpress.org/reference/classes/wp_meta_query/
$meta_query = array(
//to sort by a meta query, we have to name it
'location_status' => array(
//luckily, ACF saved custom fields with their name as the meta_key
'key' => 'location_status',
//we only want to see locations that have the status information
'compare' => 'EXISTS'
)
);
$query->set( 'meta_query', $meta_query );
//sort by: location Status DESC (first "Open", then "Closed"), then post title ASC
$query->set( 'orderby', array( 'location_status' => 'DESC', 'title' => 'ASC', 'ID' => 'ASC' ) );
}
}
}
add_action( 'pre_get_posts', 'wpse_420312_order_locations_by_open_closed' );
Happy Coding!