This Pro tutorial shows how to modify a Bricks‘ query loop parameters to only show the posts of a CPT that is indirectly related to the current single CPT item when using Meta Box.

Consider this scenario:

Custom Post Types:

  • Members
  • Orders
  • Trainings

Requirement: On a single member page, show all the related posts of training. Note that there is no direct relationship between member CPT and training CPT.

Relationships:

  • Members and Orders
  • Orders and Trainings

Sample posts:

  • Training 1 Connected From Order 2.
  • Training 2 Connected From Order 1 and 2.
  • Training 3 Connected From Order 1.
  • Member 1 Connected To Order 1.
  • Member 2 Connected To Order 2.

Objective:
When viewing Member 1, show trainings 2 and 3. This is because Member 1 is connected to Order 1 and this order is connected to Training 2 and Training 3.

Screenshots:

Relationship: Orders and Trainings

Relationship: Members and Orders

We are also going to ensure that the Section in which the indirectly related CPT items are output gets rendered only if there is at least 1 such published CPT item.

Step 1

Create a Bricks template named say “Single Member” of type “Single”.

Edit it with Bricks.

Add a Template setting condition for applying the template to Members CPT.

Add a Section having Post Title and Post Content.

Add another Section having a “Related Training” Heading. We are going to dynamically add “s” at the end of this heading text if there’s more than one published indirectly-related training for the current member.

Add a Container having a Block.

Enable Query Loop on the Block. Select Trainings CPT.

Add a Post Title inside the Block.

At this stage, all the training CPT items will be output.

Step 2

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

function bl_get_connected_trainings() {
	// orders connected from the current member
	$connected_orders = MB_Relationships_API::get_connected( [
		'id'   => 'members-and-orders',
		'from' => get_the_ID(),
	] );

	// if there are no connected orders, abort
	if ( empty( $connected_orders ) ) {
		return false;
	}

	// trainings connected from the specified orders
	$connected_trainings = MB_Relationships_API::get_connected( [
		'id' => 'orders-and-trainings',
		'from' => $connected_orders,
	] );

	foreach ( $connected_trainings as $connected_training ) {
		$connected_trainings_ids[] = $connected_training->ID;
	}

	// return the IDs after removing duplicates
	return array_unique( $connected_trainings_ids );
}

// Restrict the trainings based on the value of Meta Box relationship field
add_filter( 'bricks/posts/query_vars', function( $query_vars, $settings, $element_id ) {
	// if we are not a singular member page or Meta Box is not active, return the query vars.
	if ( ! is_singular( 'member' ) || ! function_exists( 'rwmb_meta' ) ) {
		return $query_vars;
	}

	if ( $element_id === 'oormkn' ) {
		$connected_trainings_ids = bl_get_connected_trainings();
	
		if ( $connected_trainings_ids ) {
			$query_vars['post__in'] = $connected_trainings_ids;
		}
	}

	return $query_vars;
}, 10, 3 );

function bl_get_connected_trainings_count() {
	$connected_trainings_ids = bl_get_connected_trainings();

	return $connected_trainings_ids ? count( $connected_trainings_ids ) : false;
}

// Add "s" at the end of a specific heading element's text if there is more than 1 related (by an indirect Meta Box Relationship) post.
add_filter( 'bricks/element/settings', function( $settings, $element ) {
	if ( $element->id === 'lhezos' && bl_get_connected_trainings_count() > 1 ) {
		$settings['text'] .= 's';
	}
  
	return $settings;
  }, 10, 3 );

Replace oormkn with the Bricks ID of the query loop element and lhezos with the Bricks ID of heading element.

Reference

https://brickslabs.com/meta-box-relationship-in-bricks/