Skip Navigation

[Resolved] Select box to create a date filter

This thread is resolved. Here is a description of the problem and solution.

Problem:

How to add custom filter items in the front end of the view.

Solution:

Check the details of the doc below:

Relevant Documentation:

https://toolset.com/forums/topic/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.

This topic contains 12 replies, has 3 voices.

Last updated by Christopher Amirian 8 months, 2 weeks ago.

Assisted by: Christopher Amirian.

Author
Posts
#2690483

jum

Select box to create a date filter

#2690508
#2690579

Christopher Amirian
Supporter

Languages: English (English )

Hi there,

I asked the second-tier support and waiting for the reply.

Thanks.

#2690899

jum

Hi ,

I have tried to change a code a bit when i pass URL only with this filter like this: hidden link

then the result is showing fine. But initially the URL paramter is not adding correctly when i add the filter URL it taking as

ex: wpv_view_count=43949&test-date-filter%5B%5D=last_week&
wpv_sort_orderby=post_date&wpv_sort_orderby_as=string&wpv_orderby=post_date&wpv_sort_order=desc&wpv_order=desc

I dont know why it taking %5B%5D= in the URL and this filter is not working with other filters.

{code}
[wpv-control url_param="test-date-filter" type="select" values="all,today,last_week,last_month,last_year" display_values="All,Today,Last week,Last month,Last year"]

<?php
// Add filter for modifying the query
add_filter('wpv_filter_query', 'filter_posts_by_date', 10, 3);

function filter_posts_by_date($query_args, $view_settings, $view_id) {
if ($view_id == xxxxx) {
// Check if post_published_date parameter is set in the URL
if (isset($_GET['test-date-filter']) && !empty($_GET['test-date-filter'])) {
$date_filter1 = sanitize_text_field($_GET['test-date-filter']); // Sanitize input

// Prepare date_query based on selected date filter
if ($date_filter1 == 'today') {
$query_args['date_query'] = array(
array(
'after' => 'today',
'before' => 'tomorrow',
'inclusive' => true,
),
);
} elseif ($date_filter1 == 'last_week') {
$query_args['date_query'] = array(
array(
'after' => '1 week ago',
),
);
} elseif ($date_filter1 == 'last_month') {
$query_args['date_query'] = array(
array(
'after' => '1 month ago',
),
);
} elseif ($date_filter1 == 'last_year') {
$query_args['date_query'] = array(
array(
'after' => '1 year ago',
),
);
} elseif ($date_filter1 == 'all') { // Handling for 'all' value
// No date query needed
}
}

// Pagination
if (isset($_GET['wpv_paged'])) {
$query_args['paged'] = max(1, intval($_GET['wpv_paged'])); // Sanitize and ensure page number is at least 1
} else {
$query_args['paged'] = 1;
}
}
return $query_args;
}
{code}

Please guide me how to fix this ,

Thanks for the support.

#2690977

Nigel
Supporter

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

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

Hi there

Sorry, Christopher is off, and I've reached the end of my shift, but let me reply to you tomorrow morning when I start again.

I should be able to get this working for you.

#2691110

Nigel
Supporter

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

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

This was more challenging than I expected. Working on a test site to implement this, I established that there is a problem with the legacy wpv-control shortcode which means it cannot be used for this. (That shortcode has subsequently been replaced with specific shortcodes for custom field or taxonomy filters.)

Instead of using the wpv-control shortcode it is necessary to add the markup for a form input manually.

It is possible to add the necessary markup to the View search section (via a Custom HTML block if using the block editor, or directly if using the legacy View editor), but in the solution I'll share below we will register a custom shortcode to generate the control dynamically.

Even then, there is a problem with our plugin code that effectively prevents adding custom filter controls. (We have shared solutions in the past, but they only work the first time you set a value for the filter; if you update the value and reload the page, multiple matching url parameters are added to the url and the filtering breaks. I don't know if it used to work and broke, or the users employing this solution didn't notice that it only works the first time.)

So, I am proposing to our developers a simple change in our plugin code that will enable this to work. Until such a change is made, you will need to edit the plugin code directly (I'll try to make sure the proposed changes are included in the next plugin update so that you don't have to keep editing the plugin files).

Before going any further, please edit this file: wp-content/plugins/toolset-blocks/embedded/inc/wpv-filter-embedded.php (or wp-content/plugins/wp-views/embedded/inc/wpv-filter-embedded.php if you have Views installed instead of Blocks).

Update line 1147 so that it matches this:

$query_args_remove = apply_filters( 'wpv_filter_query_args_remove', wp_list_pluck( $view_url_data, 'attribute' ), $view_id );

Now that you have made that change it is possible to add a custom filter control to your View.

There are 3 parts to the solution:

1. register a custom shortcode to generate the filter control (including maintaining the currently selected filter value) (and insert this shortcode in the Views filter control section)
2. add a filter to tell Views to strip the custom filter url parameter from the form action so that updating the filter does not append multiple versions of the parameter to the url
3. modify the query generated by the View to use the value from the custom filter

The custom code for steps 1, 2, and 3 can all go in the same code snippet, which you can add at Toolset > Settings > Custom Code, but I will share it in discrete sections below.

1. Register the shortcode

/**
 * Register shortcode to generate custom filter control
 * for post date
 */
add_shortcode("post-date-filter", "post_date_filter");
function post_date_filter() {

    // retain which option is selected
    $selection = (isset($_GET['post-date-filter']) ? $_GET['post-date-filter']: '');

    $options = [
        'Any date'      => '',
        'Today'         => '1 day ago',
        'Last week'     => '1 week ago',
        'Last month'    => '1 month ago',
        'Last year'     => '1 year ago'
    ];

    $out = "<select name='post-date-filter'>";
    
    foreach( $options as $display => $value){
        $out .= "<option " . selected($value, $selection, false) . " value='$value'>$display</option>";
    }
    
    $out .= "</select>";

    return $out;
}

Pay careful attention to the option values, such as "1 month ago". WordPress date queries are quite flexible when it comes to interpreting date-like strings, based upon strtotime.

See hidden link and https://developer.wordpress.org/reference/classes/wp_query/#date-parameters

Insert this shortcode where you want the filter control to appear (in place of the wpv-control shortcode you have been using up until now).

2. Prevent the url parameter being added multiple times

/**
 * Exclude the custom parameter from the search form action
 */
add_filter( 'wpv_filter_query_args_remove', function( $query_args_remove ){
    $query_args_remove[] = 'post-date-filter';
    return $query_args_remove;
}, 10, 1);

If you are modifying this code, note that 'post-date-filter' must match the same in the first section of code.

3. Modify the query to use the filter value

/**
 * Modify the View query based on the custom filter value
 */
add_filter( 'wpv_filter_query', 'ts_custom_date_filter', 101, 3 );
function ts_custom_date_filter( $query_args, $view_settings, $view_id ){
    if ( $view_id == 123 && isset( $_GET['post-date-filter'] ) ){
        $query_args['date_query'] = array(
            'after'     =>  $_GET['post-date-filter'],
            'column'    =>  'post_date' // or use post_modified for when post was last updated
        );
    }

    return $query_args;
}

Again, 'post-date-filter' must match the previous code, and you will also need to edit the ID of the View this should apply to (123 in the example above).

I've tested that thoroughly and expect it should work as needed, but please let us know either way.

#2691429

jum

Hi Nigel,

Thanks for the support.

As per your instruction i have updated the like 1147 in wp-content/plugins/toolset-blocks/embedded/inc/wpv-filter-embedded.php

I added the custom code you provided in settings-> add new custom code. name: register-post-date-filter and activated it

As i am new to using this custom code method i am not sure how to put this inside the view as i cant fine shortcode of it.

Please guide me how to use this custom code filter to place inside the view.

Thanks in advance,

#2691434

Nigel
Supporter

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

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

>Insert this shortcode where you want the filter control to appear (in place of the wpv-control shortcode you have been using up until now).

Sorry if that wasn't clear.

The code registers a shortcode which will output the custom filter control. The shortcode is [post-date-filter], so add that to your View where you were previously adding the wpv-control shortcode (remove that).

#2691518

jum

Hi nigel,

Thanks i have added the shortcode in my view [post-date-filter] The result is not giving the correct output.

I have changed the query as below but its also not working with view.

{code}
<?php
/**
* New custom code snippet (replace this with snippet description).
*/

toolset_snippet_security_check() or die( 'Direct access is not allowed' );

// Put the code of your snippet below this comment.
/**
* Register shortcode to generate custom filter control
* for post date
*/
add_shortcode("post-date-filter", "post_date_filter");
function post_date_filter() {

// retain which option is selected
$selection = (isset($_GET['post-date-filter']) ? $_GET['post-date-filter']: '');

$options = [
'Any date' => '',
'Today' => 'today',
'Last week' => 'last_week',
'Last month' => 'last_month',
'Last year' => 'last_year'
];

$out = "<select name='post-date-filter'>";

foreach( $options as $display => $value){
$out .= "<option " . selected($value, $selection, false) . " value='$value'>$display</option>";
}

$out .= "</select>";

return $out;
}

/**
* Exclude the custom parameter from the search form action
*/
add_filter( 'wpv_filter_query_args_remove', function( $query_args_remove ){
$query_args_remove[] = 'post-date-filter';
return $query_args_remove;
}, 10, 1);

/**
* Modify the View query based on the custom filter value
*/
add_filter( 'wpv_filter_query', 'ts_custom_date_filter', 101, 3 );
function ts_custom_date_filter( $query_args, $view_settings, $view_id ){
/*
if ( $view_id == 43949 && isset( $_GET['post-date-filter'] ) ){
$query_args['date_query'] = array(
'after' => $_GET['post-date-filter'],
'column' => 'post_date' // or use post_modified for when post was last updated
);
}
*/

if ( $view_id == 43949 && isset( $_GET['post-date-filter'] ) ){
$date_filters = $_GET['post-date-filter'];
$current_date = current_time( 'mysql' );
if ( $date_filters == 'today' ) {
$query_args['date_query'] = array(
array(
'year' => date( 'Y', strtotime( $current_date ) ),
'month' => date( 'm', strtotime( $current_date ) ),
'day' => date( 'd', strtotime( $current_date ) ),
),
);
}

elseif ( $date_filters == 'last_week' ) {
$query_args['date_query'] = array(
array(
'after' => '1 week ago',

),
);
} elseif ( $date_filters == 'last_month' ) {
$query_args['date_query'] = array(
array(
'after' => '1 month ago',

),
);
}
elseif ( $date_filters == 'last_year' ) {
// Query posts published in the last year
$query_args['date_query'] = array(
array(
'after' => '1 year ago',

),
);
}

}

return $query_args;
}
{code}

please guide me to fix this .

#2692235

jum

Any update?

#2692370

Christopher Amirian
Supporter

Languages: English (English )

Hi there,

I will need help from Nigel as I am not sure how you set things up.

I will inform him when he is available for an answer.

Thanks.

#2692545

Nigel
Supporter

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

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

Sorry for the delay.

I had some feedback from the developers about my request to add a filter that could be used to make the solution work, which I described in my previous reponse.

They have shared with me a different filter that already exists that can be used for a similar purpose, and I have been testing a solution based on that.

So I need to modify the advice somewhat.

So that I can share the solution in a clean thread that other users can also benefit from, I created and answered a forum thread with a complete description of the solution, which I would ask you to refer to here: https://toolset.com/forums/topic/how-to-add-custom-filters-such-as-for-post-author-or-post-date-to-a-view/

I have made the test site I used to while preparing the response available on a sandbox so that you can refer to it and see it working.

You can log in with this link: hidden link

You'll find the code for the solution added in Toolset > Settings > Custom Code.

The View with custom controls is added to the page Filter Posts.

You should be able to copy and paste the code from that test site to your own and should only need to edit the ID of the View this applies to, as well as changing how you add the filter control to the View, as described in that ticket.

Thanks for your patience.

#2693002

jum

Hi Nigel,

Thanks for the patience and support.

Due to my website issue, i need to create a new copy of the site.

I will try the code you provide above and let you know .

Thanks in advance,

#2693393

Christopher Amirian
Supporter

Languages: English (English )

Sure thanks.

#2694595

jum

Hi,

I tried with the code above but for me the URL is updating but the result is not showing. I have changed a code a bit and this works for me in block editor.

------------------------------------

document.addEventListener('DOMContentLoaded', function() {
var currentFilter = getCurrentFilter(); // determine current filter value

var dropdown = document.getElementById('publishedDateFilter');
dropdown.value = currentFilter; // set the dropdown value to the current filter

dropdown.addEventListener('change', function(event) {
var selectedValue = this.value;
updatePublishedDateFilter(selectedValue); // update the published date filter
});
});

function getCurrentFilter() {
var currentUrl = new URL(window.location.href);
return currentUrl.searchParams.get('post_publised_date_test') || ''; // default to an empty string if not specified
}

function updatePublishedDateFilter(value) {
var currentUrl = new URL(window.location.href);
currentUrl.searchParams.set('post_publised_date_test', value);
window.location.href = currentUrl.href;
}

.dropdown-container {
flex-direction: column;
margin-top: -5px;
}

.dropdown-wrapper {
margin-top: 0px;
}

---------------------------------------------------------------------------------------------

PHP snippet:
add_filter('wpv_filter_query', 'filter_published_date_custom_fn', 1000, 3);

function filter_published_date_custom_fn($query_args, $view_settings) {
if (!is_admin() && isset($view_settings['view_id']) && $view_settings['view_id'] == 123) {
$date_filter = $_GET['post_publised_date_test']; // Get the selected date filter from the URL
if (!empty($date_filter)) {
switch ($date_filter) {
case 'today':
$query_args['date_query'] = array(
array(
'year' => date('Y'),
'month' => date('m'),
'day' => date('d'),
),
);
break;
case 'last_week':
$query_args['date_query'] = array(
array(
'after' => '1 week ago',
),
);
break;
case 'last_7_days':
$query_args['date_query'] = array(
array(
'after' => '7 days ago',
),
);
break;
case 'last_14_days':
$query_args['date_query'] = array(
array(
'after' => '14 days ago',
),
);
break;
case 'last_28_days':
$query_args['date_query'] = array(
array(
'after' => '28 days ago',
),
);
break;
case 'last_30_days':
$query_args['date_query'] = array(
array(
'after' => '30 days ago',
),
);
break;
case 'last_60_days':
$query_args['date_query'] = array(
array(
'after' => '60 days ago',
),
);
break;
case 'last_90_days':
$query_args['date_query'] = array(
array(
'after' => '90 days ago',
),
);
break;
case 'quarter_to_date':
$query_args['date_query'] = array(
array(
'after' => '3 months ago', // Assuming quarter starts 3 months ago from current date
),
);
break;
case 'last_12_months':
$query_args['date_query'] = array(
array(
'after' => '12 months ago',
),
);
break;
case 'this_year':
$query_args['date_query'] = array(
array(
'after' => date('Y') . '-01-01', // Start of the current year
),
);
break;
case 'last_month':
$query_args['date_query'] = array(
array(
'after' => '1 month ago',
),
);
break;
case 'last_year':
$query_args['date_query'] = array(
array(
'after' => '1 year ago',
),
);
break;
default:
break;
}
}
}
return $query_args;
}

Thanks for the support