Profile picture Schedule a Meeting
c a n d l a n d . n e t

Hacking the Query Loop

Dusty Candland | | wordpress, queryloop, wpsupporthq

I've been loving building sites with the block editor and more recently sites with full site editing (FSE).

One thing I've run into a few times is the need to hack the Query Loop block with some additional filtering and sorting.

Both time were event related. For the latest site, we created an event type using Pods Framework, storing the fields as postmeta.

For events, you'll want to sort by a date, like start_date and sometimes files past events.

The query loop supports a search field. I've been using that to hack the loop with sorting and filtering. The basic idea is to intercept the query and split it into other supported query options.

For example: order:asc|orderby:start_date|meta_key:start_date|meta:start_date;$today;<

That command, will set the order, orderby, and meta_key for sorting. Then the meta key, will do a meta_query filtering for start_date less than $today.

$today is a special value that gets today formatted as yyyy-mm-dd.

Add the following to the functions.php file in the child theme.

add_action( 'pre_get_posts', function( \WP_Query $query ) {
	if ( $query->is_search() && str_contains( $query->get( 's' ), ":" ) ) {
		// Editor html encodes <
		$args = html_entity_decode($query->get( 's', '' ));
		// echo "Args: " . $args . "<br>";

		// Clear search query
		$query->set( 's', '' );

		$commands = preg_split( "/\|/", $args );

		// Loop through filters
		// order, orderby, s, post_type, posts_per_page, paged, meta_key
		foreach ( $commands as $command ) {
			// Split filter into key and value
			$command = preg_split( "/:/", $command );
			$key = $command[0];
			$value = $command[1];

			if ( $key === 'meta' ) {
				$params = preg_split( "/;/", $value );
				$param_key = $params[0];
				$param_value = $params[1];
				$param_compare = $params[2];

				if ( $param_value == '$today' ) {
					$param_value = date( 'Y-m-d' );
				}

				// echo "Adding: " . $param_key . " " . $param_compare . " " . $param_value . "<br>";
				$query->set('meta_query', array(
					array(
						'key' => $param_key,
						'value' => $param_value,
						'compare' => $param_compare,
					),
				));
			} else {
				// Add command to query
				$query->set( $key, $value );
				// echo "Adding: " . $key . " => " . $value . "<br>";
			}
		}
	}
} );

Definitely not exhaustive or super intuitive, but it gets the job done and is usable for any Query Loop.

Webmentions

These are webmentions via the IndieWeb and webmention.io. Mention this post from your site: