Upcoming Events Accordion in Bricks Grouped by ‘Month Year’

This Pro tutorial is a variation of the previous Upcoming Events Grouped by ‘Month Year’ in Bricks tutorial wherein the upcoming ‘month year’s are shown in BricksExtras Pro Accordion with the events corresponding to that month and year with the dates based on event_date post meta value.

Given this events list:

the output after implementing the tutorial as on 17 Jul 2024 would be:

We shall loop through the events, construct an array with the necessary data, set up a custom Bricks query type for the ‘month year’ query loop and an inner event posts query loop that uses the outer query loop object to pull the post IDs.

Step 1

Create the CPT and corresponding date-type custom field. ACF was used in our dev site.

CPT: event

Custom field: event_date
Return format: Ymd

Create event posts and populate the event date field for each.

Step 2

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

<?php

if ( ! function_exists( 'bl_get_event_year_data_20240717' ) ) {
    function bl_get_event_year_data_20240717(): array {
        // Query arguments
        $args = [
            'post_type' => 'event',
            'posts_per_page' => -1, // Get all events
            'meta_key' => 'event_date',
            'orderby' => 'meta_value',
            'order' => 'ASC',
            'meta_query' => [
                [
                    'key' => 'event_date',
                    'compare' => 'EXISTS',
                    'type' => 'DATE',
                ],
                [
                    'key' => 'event_date',
                    'compare' => '>=',
                    'value' => date( 'Ymd' ),
                ],
            ],
        ];

        // Get all future event posts
        $events = get_posts( $args );

        $unique_months = [];

        foreach ( $events as $event ) {
            $event_date = get_post_meta( $event->ID, 'event_date', true );

            if ( $event_date ) {
                // Convert the date to a DateTime object
                $date = DateTime::createFromFormat( 'Ymd', $event_date );

                if ( $date ) {
                    // Format the date as "F Y" for the key and "Ym" for sorting
                    $month_year = $date->format( 'F Y' ); // Ex.: September 2024
                    $sort_key = $date->format( 'Ym' ); // Ex.: 202409

                    // If this month_year doesn't exist in the array yet, initialize it with an empty array
                    if ( ! isset( $unique_months[$sort_key] ) ) {
                        $unique_months[$sort_key] = [
                            'month_year' => $month_year,
                            'ids' => []
                        ];
                    }

                    // Add the current event post ID to the array for this month_year
                    $unique_months[$sort_key]['ids'][] = $event->ID;
                }
            }
        }

        // Sort the array by keys (which are in "Ym" format)
        ksort( $unique_months );

        return $unique_months; // https://d.pr/i/X6t3sn
    }
}

// Add new "Month Years" query loop type option in the dropdown.
add_filter( 'bricks/setup/control_options', function( $control_options ): array {
	$control_options['queryTypes']['month_years'] = esc_html__( 'Month Years' );

	return $control_options;
} );

// Run new query if option selected.
add_filter( 'bricks/query/run', function( $results, $query_obj ): array {
	if ( $query_obj->object_type !== 'month_years' ) return $results;

	// if option is selected, run our new query
	if ( $query_obj->object_type === 'month_years' ) {
		$results = bl_get_event_year_data_20240717();
	}

	return $results;
}, 10, 2 );

// Function to get the current looping object (array).
if ( ! function_exists( 'bl_get_loop_object_array' ) ) {
	function bl_get_loop_object_array(): array {
		$looping_query_id = BricksQuery::is_any_looping();

		if ( $looping_query_id ) {
			return BricksQuery::get_loop_object( $looping_query_id );
		}

		// fallback, this won't be the one that's output
		return [];
	}
}

Step 3

Whitelist the bl_get_loop_object_array function.

Ex.:

<?php 

add_filter( 'bricks/code/echo_function_names', function() {
  return [
    'bl_get_loop_object_array'
  ];
} );

You should also add other functions (native or custom) being used in your Bricks instance besides bl_get_loop_object_array. This can be checked at Bricks → Settings → Custom code by clicking the Code review button.

More info on whitelisting can be found here.

Step 4

Install and activate BricksExtras.

Activate the license, go to its settings and enable Pro Accordion.

Step 5

Edit the Page in which you would like to output the events with Bricks.

Copy this JSON (of a section) and paste.

Query loop set on the Accordion Item:

Heading text:

{echo:bl_get_loop_object_array():array_value|month_year}

Query loop on the Block:

return [
	'post_type' => 'event',
	'posts_per_page' => -1, // all matching events
	'no_found_rows' => true,
	'post__in' => bl_get_loop_object_array()['ids'],
	'orderby' => 'post__in',
];

Sign code and save.

Check the front end.