Skip Navigation

[Resolved] How to add custom filters such as for post author or post date to a View?

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

Sun Mon Tue Wed Thu Fri Sat
- 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 -
- 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 -

Supporter timezone: Europe/London (GMT+00:00)

This topic contains 2 replies, has 1 voice.

Last updated by Nigel 7 months, 2 weeks ago.

Assisted by: Nigel.

Author
Posts
#2692531

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

It is possible to add filters for custom fields or for taxonomies to a custom search View, as well as post relationship filters. But it isn't possible to add filters for standard WordPress fields, such as for the post author, or for post dates (when a post was published, or modified).

How can we add such custom filters to a View?

#2692541

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

It is possible to add custom filters to a View that cannot ordinarily be added through the View editor, such as for post fields like the post author or post date.

It requires some coding, which I will describe below.

There are 3 parts to any solution.

The first is to add a filter control to the output of the View, so that users can select the value to filter by. Because this is a custom control it won't be possible to insert it using the normal UI, it will need to be inserted using a shortcode.

The second is a requirement to register the parameter used by this control with Views, as the search parameters require special handling.

The third is to use the Views API to modify the database query to use the value of the filter, if provided.

I will share two examples, for the more popular use cases of filtering by post date, and for filtering by post author.

I recommend adding one code snippet at Toolset > Settings > Custom Code with the relevant code for each custom filter added.

Below I detail adding a post date filter. I will share details of adding a post author filter in a separate reply.

Adding a post date filter
Say we want to add a filter that is a select dropdown which offers several choices, such as posts within the last week, within the last month, within the last year, etc.

The first part involves adding the dropdown to the filter section. In this example, the legacy Views shortcode wpv-control can be used. In the legacy Views editor you can add shortcodes directly, but with the block editor you will need to insert a Shortcode block or Custom HTML block and add the shortcode there.

We will add this shortcode:

[wpv-control url_param="date_filter" type="select" values=",1 day ago,1 week ago,1 month ago,1 year ago" display_values="Anytime,Today,Past week,Past month,Past year"]

Note that it specifies the URL parameter that will be used for this filter ("date_filter"), and that the values for the select options are passed as a list in the "values" attribute, while the corresponding option labels are passed in the "display_values" attribute. (The first list item in the values attribute is empty, corresponding to the "Anytime" label for when no filter value is selected.)

The second part of the solution is to register the URL parameter attributes with Views, as shown here.

It is only necessary to update the ID of the View this filter is being added to, along with the attribute element to specify the URL parameter used by the filter.

add_filter( 'wpv_filter_register_url_parameters_for_posts', function( $attributes, $viewSettings ) {

	if ($viewSettings['view_id'] == 123 ) { // Edit ID of View as required

      	// Register the custom URL parameter author_filter
		$attributes[] = [
			'attribute'    => 'date_filter', // the URL parameter for this filter
            // generic values, ignore
			'query_type'   => 'posts',
			'filter_type'  => 'custom',
			'filter_label' => 'Custom',
			'expected'     => 'string',
			'value'        => 'id',
			'placeholder'  => '',
			'description'  => '',
		];
	}

	return $attributes;
}, 99, 2 );

The third step is to use the Views API to modify the resulting query whenever the search filter is used and apply its value. In this example we will use 'post_modified' for the comparison rather than 'post_date', i.e. when the post was last edited rather than created.

This means using the wpv_filter_query hook, as shown below.

It is necessary to edit the View ID this should apply to, and also to edit the URL parameter (in this case 'date_filter' which occurs 3 times below).

// 3. modify View query filter to apply filter value
add_filter( 'wpv_filter_query', function($query_args, $view_settings, $view_id){

    if ( $view_id == 123 && isset($_GET['date_filter']) && !empty($_GET['date_filter'][0]) ){
    
        $query_args['date_query'] = array(
            'after'     =>  $_GET['date_filter'][0],
            'column'    =>  'post_modified'
        );
    }
    
    return $query_args;
}, 101, 3 );

Be aware if you are modifying this solution to your own needs that when you insert a filter control using the wpv-control shortcode, it treats the URL parameters as arrays (check the $_GET object and you will observe the value of the date_filter parameter will be available in $_GET['date_filter'][0] rather than just $_GET['date_filter'].

This example takes advantage of the flexible interpretation of "dates" in the WordPress date query, see hidden link and https://developer.wordpress.org/reference/classes/wp_query/#date-parameters

The three steps above should give you a functioning post date custom filter.

#2692543

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+00:00)

The process for adding a Post Author filter involves the same 3 steps as the Post Date example.

But this time, in the first step, the wpv-control is not suitable for inserting the filter control. We want a select dropdown, but now we want a dynamically-generated list of post authors, and for that we will instead register a custom shortcode [author_filter] which can be added to the filter section of the View (again, using a Shortcode block or Custom HTML block when working with the block editor).

That shortcode will query the database to get an array of IDs of users who have authored posts of a specified type (in this example, just the default Post post type), and it will use that to output the markup of a select dropdown with the users as options.

The entire code solution for steps 1, 2, and 3 follows:

/**
 * Setup author filter
 * 
 * URL parameter for this control: author_filter
 * 
 * 1. register shortcode [author_filter] to generate filter control
 * 2. register author_filter url parameter with Views
 * 3. modify View query filter to apply filter value
 */

// 1. register shortcode [author_filter] to generate filter control
add_shortcode('author_filter', function(){

    // retain which option is currently selected if any
    $selection = (isset($_GET['author_filter']) ? $_GET['author_filter']: '');

	// get an array of IDs of users who have authored posts of specified type
	global $wpdb;

    $query = <<<EOT
	SELECT DISTINCT p.post_author
	FROM {$wpdb->posts} p
	WHERE p.post_type = 'post'
	AND p.post_status = 'publish'
	EOT;

	$author_ids = $wpdb->get_col($query);

	// get corresponding users (we need their names, not just their IDs)
	$users = get_users( [ 'include' => $author_ids ]);

	// Start to build a string with the form control
	$out = "<select name='author_filter'>";
	$out .= "<option value=''>Any author</option>";

	foreach ($users as $user){
		$out .= "<option " . selected( $user->ID, $selection, false ) . " value='{$user->ID}'>{$user->display_name}</option>";
	}

	$out .= "</select>";

	return $out;
});

// 2. register author_filter url parameter to work with specified View
add_filter( 'wpv_filter_register_url_parameters_for_posts', function( $attributes, $viewSettings ) {

	if ($viewSettings['view_id'] == 123 ) { // Edit ID of View as required

      	// Register the custom URL parameter author_filter
		$attributes[] = [
			'attribute'    => 'author_filter', // Edit with URL parameter
            // ignore these defaults
			'query_type'   => 'posts',
			'filter_type'  => 'custom',
			'filter_label' => 'Custom',
			'value'        => 'id',
			'expected'     => 'string',
			'placeholder'  => '',
			'description'  => '',
		];
	}

	return $attributes;
}, 99, 2 );


// 3. modify View query filter to apply filter value
add_filter( 'wpv_filter_query', function($query_args, $view_settings, $view_id){

    if ( $view_id == 123 && isset($_GET['author_filter']) && !empty($_GET['author_filter']) ){
    
        $query_args['author'] = $_GET['author_filter'];
    }
    
    return $query_args;
}, 101, 3 );

As with the previous example, you will need to edit the ID of the View this should apply to, and if adapting to other uses you will need to edit mentions of the URL parameter author_filter, as well as the query used to get the values to use in the custom shortcode.