Filtering Posts of a Bricks Query Loop by Meta Box Group’s Subfield Value

Updated on 8 Nov 2024

In the comments section of Sort Posts by Meta Box Group Sub Field in Bricks tutorial, a user asked:

That worked wonderfully! Is there also a tutorial how to show past events when the event year is in a group? Also how to show only future events in this scenario? : )

Consider this scenario:

CPT: event

Field group:
Meta Box Group-type field: event_group
|__ Number-type subfield: event_year

Test data:

When querying the event post type, all the event posts will be output by default:

The objective is to output only the events that are in the past.

i.e., as of 2024:

or only future/upcoming events:

This is not straightforward or doable via the built-in query editor controls due to the fact that the event year post meta is inside a Meta Box group.

This Pro tutorial shows how bricks/query/result Bricks filter can be used to limit the posts output by a Posts query loop based on the value of a Meta Box group’s subfield value.

Update 1: Code for the case when the subfield type is Datepicker has been added near the end.

Step 1

Set up a query loop to output Events post type.

Add Heading/Basic Text etc. elements inside the query loop-enabled Block and map them to your post data like post title and the year subfield value.

Step 2

Add the following in child theme‘s functions.php (w/o the opening PHP tag) or a code snippets plugin:

<?php

/**
 * Filter Bricks query results to show only past events based on event_year field
 * 
 * @param mixed     $result    The query result (can be array or WP_Query)
 * @param object    $query_obj The Bricks query object containing element info
 * @return mixed Modified query result
 */
add_filter( 'bricks/query/result', function( $result, object $query_obj ) {
    // Return early if not our target element or post type
    if ( $query_obj->element_id !== 'smtmwj' || $query_obj->object_type !== 'post' ) {
        return $result;
    }

    // Get current year for comparison
    $current_year = (int) date( 'Y' );

    // Handle both array and WP_Query results
    $posts = is_array( $result ) ? $result : ( $result->posts ?? [] );

    if ( ! empty( $posts ) ) {
        $filtered_posts = [];
        
        foreach ( $result->posts as $post ) {
            // Get the event year from Meta Box group field
            $event_data = rwmb_get_value( 'event_group', [], $post->ID );
            
            // Add post to filtered results if event_year exists and is in the past
            if ( 
                ! empty( $event_data['event_year'] ) && 
                (int) $event_data['event_year'] < $current_year 
            ) {
                $filtered_posts[] = $post;
            }
        }
        
        // Update the result based on its type
        if ( is_array( $result ) ) {
            $result = $filtered_posts;
        } else {
            $result->posts = $filtered_posts;
            $result->post_count = count( $filtered_posts );
            $result->found_posts = count( $filtered_posts );
            $result->current_post = -1;
        }
    }

    return $result;
}, 10, 2 );

Replace smtmwj with the Bricks ID of your query loop-enabled Block.

Now the posts will be filtered to only output the past events.

To output only future events, replace

! empty( $event_data['event_year'] ) && 
                (int) $event_data['event_year'] < $current_year

with

! empty( $event_data['event_year'] ) && 
                (int) $event_data['event_year'] > $current_year

Update 1: Code for the case when the subfield type is Datepicker

<?php

/**
 * Filter Bricks query results to show only past events based on event_date field
 * 
 * @param mixed     $result    The query result (can be array or WP_Query)
 * @param object    $query_obj The Bricks query object containing element info
 * @return mixed Modified query result
 */
add_filter( 'bricks/query/result', function( $result, object $query_obj ) {
    // Return early if not our target element or post type
    if ( $query_obj->element_id !== 'smtmwj' || $query_obj->object_type !== 'post' ) {
        return $result;
    }

    // Get current date for comparison
    $current_date = date( 'Y-m-d' );

    // Handle both array and WP_Query results
    $posts = is_array( $result ) ? $result : ( $result->posts ?? [] );

    if ( ! empty( $posts ) ) {
        $filtered_posts = [];
        
        foreach ( $result->posts as $post ) {
            // Get the event date from Meta Box group field
            $event_data = rwmb_get_value( 'event_group', [], $post->ID );
            
            // Add post to filtered results if event_date exists and is in the past
            if ( 
                ! empty( $event_data['event_date'] ) && 
                strtotime( $event_data['event_date'] ) < strtotime( $current_date ) 
            ) {
                $filtered_posts[] = $post;
            }
        }
        
        // Update the result based on its type
        if ( is_array( $result ) ) {
            $result = $filtered_posts;
        } else {
            $result->posts = $filtered_posts;
            $result->post_count = count( $filtered_posts );
            $result->found_posts = count( $filtered_posts );
            $result->current_post = -1;
        }
    }

    return $result;
}, 10, 2 );