/** * Advanced Directory Filtering: Handles Open Now, Cuisine, Price Ranges, and Sort Orders. * Intercepts both the main archive query AND our custom front-page queries. */ function freshlanta_apply_directory_filters( $query ) { // Only run on front-end restaurant queries flagged with 'freshlanta_directory' OR the main archive if ( is_admin() || $query->get('post_type') !== 'restaurant' ) { return; } if ( ! $query->is_main_query() && ! $query->get('freshlanta_directory') ) { return; } // 1. Keyword Search if ( isset( $_GET['s'] ) && ! empty( $_GET['s'] ) ) { $query->set( 's', sanitize_text_field( $_GET['s'] ) ); } // 2. Cuisine Taxonomy if ( isset( $_GET['cuisine'] ) && ! empty( $_GET['cuisine'] ) ) { $tax_query = $query->get( 'tax_query' ) ?: array(); $tax_query[] = array( 'taxonomy' => 'cuisine', 'field' => 'slug', 'terms' => sanitize_text_field( $_GET['cuisine'] ), ); $query->set( 'tax_query', $tax_query ); } // Safely pull existing meta_query variables so we don't overwrite the Slotting Engine $meta_query = $query->get( 'meta_query' ) ?: array(); $meta_query['relation'] = 'AND'; // 3. Price Range Meta Query if ( isset( $_GET['price_range'] ) && ! empty( $_GET['price_range'] ) ) { $meta_query[] = array( 'key' => 'price_range', 'value' => sanitize_text_field( $_GET['price_range'] ), 'compare' => '=' ); } // 4. Open Now Logic (Cached so it only hits the database once!) if ( isset( $_GET['open_now'] ) && $_GET['open_now'] === 'yes' ) { static $open_restaurant_ids = null; if ( $open_restaurant_ids === null ) { global $wpdb; $current_datetime = current_datetime(); $current_day = strtolower( $current_datetime->format('l') ); $current_time = $current_datetime->format('H:i'); $sql = " SELECT p.ID FROM {$wpdb->posts} p LEFT JOIN {$wpdb->postmeta} m_closed ON (p.ID = m_closed.post_id AND m_closed.meta_key = %s) INNER JOIN {$wpdb->postmeta} m_open ON (p.ID = m_open.post_id AND m_open.meta_key = %s) INNER JOIN {$wpdb->postmeta} m_close ON (p.ID = m_close.post_id AND m_close.meta_key = %s) WHERE p.post_type = 'restaurant' AND p.post_status = 'publish' AND (m_closed.meta_value IS NULL OR m_closed.meta_value != '1') AND m_open.meta_value != '' AND m_close.meta_value != '' AND ( ( CAST(m_open.meta_value AS TIME) < CAST(m_close.meta_value AS TIME) AND CAST(%s AS TIME) >= CAST(m_open.meta_value AS TIME) AND CAST(%s AS TIME) <= CAST(m_close.meta_value AS TIME) ) OR ( CAST(m_open.meta_value AS TIME) > CAST(m_close.meta_value AS TIME) AND ( CAST(%s AS TIME) >= CAST(m_open.meta_value AS TIME) OR CAST(%s AS TIME) <= CAST(m_close.meta_value AS TIME) ) ) ) "; $prepared_sql = $wpdb->prepare( $sql, 'closed_' . $current_day, 'open_' . $current_day, 'close_' . $current_day, $current_time, $current_time, $current_time, $current_time ); $open_restaurant_ids = $wpdb->get_col($prepared_sql); } if ( empty($open_restaurant_ids) ) { $query->set( 'post__in', array(0) ); // Force empty } else { $query->set( 'post__in', $open_restaurant_ids ); } } // 5. Sort Order $sort_order = isset( $_GET['sort_order'] ) ? sanitize_text_field( $_GET['sort_order'] ) : ''; if ( $sort_order === 'az' ) { $query->set( 'orderby', 'title' ); $query->set( 'order', 'ASC' ); } elseif ( $sort_order === 'highest_rated' ) { $meta_query['rating_clause'] = array( 'relation' => 'OR', array( 'key' => 'average_rating', 'compare' => 'EXISTS' ), array( 'key' => 'average_rating', 'compare' => 'NOT EXISTS' ) ); $query->set( 'orderby', array( 'rating_clause' => 'DESC', 'date' => 'DESC' ) ); } else { // Default Organic Sort: Newest (Sponsors are handled in the template now) if ( ! $query->get('orderby') ) { $query->set( 'orderby', 'date' ); $query->set( 'order', 'DESC' ); } } $query->set( 'meta_query', $meta_query ); } add_action( 'pre_get_posts', 'freshlanta_apply_directory_filters' );