Last active
October 8, 2026 12:30
-
-
Save jmabbas/a89259a0e8d5d9aa7955842bfe37c83b to your computer and use it in GitHub Desktop.
GoTrek - Search box input update
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
| // 1. Ensure search query variables are registered | |
| add_filter( 'query_vars', function( $vars ) { | |
| $vars[] = 'location'; | |
| $vars[] = 'adults'; | |
| $vars[] = 'children'; | |
| $vars[] = 'rooms'; | |
| return $vars; | |
| } ); | |
| // 2. Hook into the main WooCommerce product query | |
| add_action( 'pre_get_posts', 'gotrek_serverside_hotel_filter', 20 ); | |
| function gotrek_serverside_hotel_filter( $query ) { | |
| // Only modify main queries on the frontend catalog and product search | |
| if ( is_admin() || ! $query->is_main_query() ) { | |
| return; | |
| } | |
| $post_type = $query->get( 'post_type' ); | |
| if ( 'product' !== $post_type && ! ( is_post_type_archive( 'product' ) || is_shop() ) ) { | |
| return; | |
| } | |
| $location = sanitize_text_field( get_query_var( 'location', '' ) ); | |
| $adults = absint( get_query_var( 'adults', 0 ) ); | |
| $children = absint( get_query_var( 'children', 0 ) ); | |
| $rooms = absint( get_query_var( 'rooms', 0 ) ); | |
| // If no search parameters are present, leave standard catalog query untouched | |
| if ( empty( $location ) && $adults === 0 && $children === 0 && $rooms === 0 ) { | |
| return; | |
| } | |
| // A. Filter by Location (supports both ACF address map and text location) | |
| if ( ! empty( $location ) ) { | |
| $meta_query = (array) $query->get( 'meta_query' ); | |
| $meta_query[] = array( | |
| 'relation' => 'OR', | |
| array( | |
| 'key' => 'hotel_group_location_map', | |
| 'value' => $location, | |
| 'compare' => 'LIKE', | |
| ), | |
| array( | |
| 'key' => 'hotel_group_location', | |
| 'value' => $location, | |
| 'compare' => 'LIKE', | |
| ), | |
| ); | |
| $query->set( 'meta_query', $meta_query ); | |
| } | |
| // B. Filter by Guest & Room Capacity | |
| if ( $adults > 0 || $children > 0 || $rooms > 0 ) { | |
| $matching_ids = gotrek_get_matching_capacity_hotel_ids( $adults, $children, $rooms ); | |
| if ( ! empty( $matching_ids ) ) { | |
| $existing_post_in = $query->get( 'post__in' ); | |
| if ( ! empty( $existing_post_in ) ) { | |
| $matching_ids = array_intersect( $existing_post_in, $matching_ids ); | |
| } | |
| $query->set( 'post__in', ! empty( $matching_ids ) ? $matching_ids : array( 0 ) ); | |
| } else { | |
| // No hotels meet capacity -> return empty set cleanly | |
| $query->set( 'post__in', array( 0 ) ); | |
| } | |
| } | |
| } | |
| /** | |
| * Helper: Query hotel products matching capacity requirements. | |
| * Cached in transients to prevent database overhead. | |
| */ | |
| function gotrek_get_matching_capacity_hotel_ids( $req_adults, $req_children, $req_rooms ) { | |
| $cache_key = sprintf( 'gotrek_cap_a%d_c%d_r%d', $req_adults, $req_children, $req_rooms ); | |
| $cached_ids = get_transient( $cache_key ); | |
| if ( false !== $cached_ids ) { | |
| return $cached_ids; | |
| } | |
| $all_hotels = get_posts( array( | |
| 'post_type' => 'product', | |
| 'posts_per_page' => -1, | |
| 'post_status' => 'publish', | |
| 'fields' => 'ids', | |
| 'meta_query' => array( | |
| 'relation' => 'OR', | |
| array( | |
| 'key' => 'hotel_group_rooms', | |
| 'compare' => 'EXISTS', | |
| ), | |
| array( | |
| 'key' => 'room_group_max_adult', | |
| 'compare' => 'EXISTS', | |
| ), | |
| ), | |
| ) ); | |
| $matching_ids = array(); | |
| foreach ( $all_hotels as $product_id ) { | |
| $hotel_rooms = get_post_meta( $product_id, 'hotel_group_rooms', true ); | |
| // Scenario 1: Parent Hotel with associated Rooms | |
| if ( ! empty( $hotel_rooms ) && is_array( $hotel_rooms ) ) { | |
| $rooms_count = count( $hotel_rooms ); | |
| $max_adults = 0; | |
| $max_children = 0; | |
| $total_adults = 0; | |
| $total_children = 0; | |
| foreach ( $hotel_rooms as $room ) { | |
| $room_id = is_object( $room ) ? $room->ID : absint( $room ); | |
| $r_adults = 0; | |
| $r_child = 0; | |
| if ( function_exists( 'get_field' ) ) { | |
| $rg = get_field( 'room_group', $room_id, false ); | |
| if ( is_array( $rg ) ) { | |
| $r_adults = isset( $rg['max_adult'] ) ? absint( $rg['max_adult'] ) : 0; | |
| $r_child = isset( $rg['max_children'] ) ? absint( $rg['max_children'] ) : 0; | |
| } | |
| } | |
| if ( ! $r_adults ) { | |
| $r_adults = absint( get_post_meta( $room_id, 'room_group_max_adult', true ) ); | |
| } | |
| if ( ! $r_child ) { | |
| $r_child = absint( get_post_meta( $room_id, 'room_group_max_children', true ) ); | |
| } | |
| $total_adults += $r_adults; | |
| $total_children += $r_child; | |
| if ( $r_adults > $max_adults ) $max_adults = $r_adults; | |
| if ( $r_child > $max_children ) $max_children = $r_child; | |
| } | |
| // Exceeds available rooms count | |
| if ( $req_rooms > 0 && $rooms_count < $req_rooms ) { | |
| continue; | |
| } | |
| // Single room request: check single room capacity | |
| if ( $req_rooms === 1 ) { | |
| if ( $req_adults > 0 && $req_adults > $max_adults ) continue; | |
| if ( $req_children > 0 && $req_children > $max_children ) continue; | |
| } else { | |
| // Multi-room request: check total capacity | |
| if ( $req_adults > 0 && $req_adults > $total_adults ) continue; | |
| if ( $req_children > 0 && $req_children > $total_children ) continue; | |
| } | |
| $matching_ids[] = $product_id; | |
| } else { | |
| // Scenario 2: Direct standalone Room product | |
| $r_adults = absint( get_post_meta( $product_id, 'room_group_max_adult', true ) ); | |
| $r_child = absint( get_post_meta( $product_id, 'room_group_max_children', true ) ); | |
| if ( $req_rooms > 1 ) continue; | |
| if ( $req_adults > 0 && $req_adults > $r_adults ) continue; | |
| if ( $req_children > 0 && $req_children > $r_child ) continue; | |
| $matching_ids[] = $product_id; | |
| } | |
| } | |
| set_transient( $cache_key, $matching_ids, HOUR_IN_SECONDS ); | |
| return $matching_ids; | |
| } | |
| // Invalidate cache when any hotel/room product is updated | |
| add_action( 'save_post_product', function() { | |
| global $wpdb; | |
| $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '_transient_gotrek_cap_%' OR option_name LIKE '_transient_timeout_gotrek_cap_%'" ); | |
| } ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment