Query filters

The WordPress Query Loop block can be used to display posts in the Block Editor. It has settings for a post type, ordering, whether to include sticky posts or not and some filtering capabilities.

ska-blocks plugin provides an API to create Query filters for overriding what posts a specific Query Loop block will render.

By default the Previous post, Next post and Related posts filters are defined. These are used by ska-theme to provide Template parts for Posts navigation as well as Related posts which are both using the Query Loop block with query filters to achieve their functionality.

When a filter is selected, the WordPress core query_loop_block_query_vars filter is used to override the query that the block will use.

Add a custom filter

Additional query filters can be registered with the following code:

Registering a custom queryPHP
add_action('ska_blocks_init', function() {

	ska_blocks()->get('query-filters')->register_filter([
		'slug' => 'query-slug',
		'label' => 'Query label',
		'callback' => function($query, $block, $page) {
			return [];
		},
	]);
});

You should provide a slug, label and a callback to the register_filter function. The callback function should return an array of arguments for WP_Query.

The arguments for the callback function are as follows:

/**
 * @param array $query Array containing parameters for `WP_Query` as parsed by the block context.
 * @param WP_Block $block Block instance.
 * @param int $page Current query's page.
 */

Once added your custom query filter should show up in the controls for the Query Loop block:

Enabling a filter will use the arguments from the callback function when rendering the block on the front end. In the block editor the posts that are shown will still use the configuration from the original Query Loop block.

Examples

Copy and modify the example code to create your own custom query filters. Ideally such code should be placed in your child theme’s functions.php file. Using the ska_blocks_init action instead of init ensures that the code is only run when the ska-block plugin is activated and the ska_blocks() functions is available.

Previous post

Here’s how the Previous post query filter is implemented:

Previous post query filterPHP
add_action('ska_blocks_init', function() {

	ska_blocks()->get('query-filters')->register_filter([
		'slug' => 'previous-post',
		'label' => __('Previous post', 'ska-blocks'),
		'callback' => function($query, $block, $page) {

			if($prev_post = get_adjacent_post(false, '', true, 'category')) {
				return [
					'post__in' => [$prev_post->ID],
					'posts_per_page' => 1,
					'ignore_sticky_posts' => true,
				];
			}

			return [];
		},
	]);
});

Since WordPress already comes with the get_adjacent_post() function, it is used to retrieve the ID of the previous post. Once the ID is known, it is simply passed to the WP_Query arguments so that it returns this particular post.

Related posts

Here’s how the Related posts filter is implemented:

Related posts query filterPHP
add_action('ska_blocks_init', function() {

	ska_blocks()->get('query-filters')->register_filter([
		'slug' => 'related-posts',
		'label' => __('Related posts', 'ska-blocks'),
		'callback' => function($query, $block, $page) {

			$related_query = array_merge($query, [
				'post_type' => get_post_type(),
				'post__not_in' => array_merge([get_the_ID()], $query['post__not_in'] ?? []),
				'orderby' => 'rand',
				'ignore_sticky_posts' => true,
				'tax_query' => [],
			]);

			$post = get_post();
			$taxonomies = get_object_taxonomies($post, 'names');

			foreach($taxonomies as $taxonomy) {

				$terms = get_the_terms($post->ID, $taxonomy);
				if(empty($terms)) {
					continue;
				}

				$term_list = wp_list_pluck($terms, 'slug');
				$related_query['tax_query'][] = [
					'taxonomy' => $taxonomy,
					'field' => 'slug',
					'terms' => $term_list,
				];
			}

			if(count($related_query['tax_query']) > 1) {
				$related_query['tax_query']['relation'] = 'OR';
			}

			return $related_query;
		},
	]);
});

That one is a lot more complex, it merges arguments from the original Query Loop block to retain the necessary post type, and post count arguments. The current post is excluded from being a related post, and additional info about the current post is gathered for inclusion as a tax_query.