phpwordpressplugins

How do I restrict the results by date range based on which S&F Pro form is used while allowing a date range in the search form?


We are using the Search & Filter Pro plugin on our WordPress site and need to be able to restrict results for two particular categories by preset dates. I am trying to accomplish this without having to manually edit over 1000 posts to change the category or add a category, or require us to tag it a certain way to separate the posts into eras.

My preference is to restrict the dates that can be entered in the form with a min date on some forms and a min and max date on others. In version 2, I don't see a way to set a min and/or max date on the date range control in the search form and can't even begin to figure out how to do that in code (PHP or JS). It would greatly improve the user experience if users can't enter a date outside the range so that the results match the entered dates. I can filter behind the scenes using the below code.

I have managed to find a code snippet, and modified it, for altering the query for specific S&F Pro forms:

function filter_media_release_current_term( $query_args, $sfid ) {

    if($sfid==2530 || $sfid==2488)
    {
        $currentafter = 2025;
        $startyear = '2025';
        $aftermonth = '01';
        $afterday = '01';
        $currentbefore = '2025';
        // edit later to use a full date, not just year
        // if no date query set the after value
        if (!isset($query_args['date_query'])) {
            $query_args['date_query'] = 
                array(
                    'after'     => array (
                        'day'   => $afterday,
                        'month' => $aftermonth,
                        'year'  => $startyear,
                    ),
                    'inclusive' => true,
                );
        } else {
            // One or both dates are entered: see if they entered a 'To:' date and grab those values
            if (isset($query_args['date_query']['before']) && isset($query_args['date_query']['before']['year'])) {
                $currentbefore = $query_args['date_query']['before']['year'];
                $beforeday = $query_args['date_query']['before']['day'];
                $beforemonth = $query_args['date_query']['before']['month'];
                if ($currentbefore < $startyear) {
                    // can't return any results prior to the start date - resets the date query to default
                    print_r("<br/><span style='color: red'>&nbsp;&nbsp;Enter dates starting " . $aftermonth ."/" . $afterday . "/" . $startyear . "</span><br/><br/>");
                    $query_args['date_query'] = 
                    array(
                        'after'     => array (
                            'day'   => $afterday,
                            'month' => $aftermonth,
                            'year'  => $startyear,
                        ),
                        'inclusive' => true,
                    );
                } else {
                    // Before date is valid
                    // Did they enter a 'From:' date?
                    if (isset($query_args['date_query']['after']) && isset($query_args['date_query']['after']['year'])) {
                        $currentafter = $query_args['date_query']['after']['year'];
                        // if before start date - reset it to the start date but keep the before entry
                        if ($currentafter < $startyear) {
                            print_r("<br/><span style='color: red'>&nbsp;&nbsp;Start date out of range!</span><br/><br/>");
                            $query_args['date_query'] = 
                                array(
                                    'after'     => array (
                                        'day'   => $afterday,
                                        'month' => $aftermonth,
                                        'year'  => $startyear,
                                    ),
                                    'before'     => array (
                                        'day'   => $beforeday,
                                        'month' => $beforemonth,
                                        'year'  => $currentbefore,
                                    ),
                                    'inclusive' => true,
                                );
                        } // no else here - do nothing if both dates are in the valid range
                    } else {
                        // no 'From:' date entered - use default from date and the 'To:' date they entered
                        $query_args['date_query'] = 
                            array(
                                'after'     => array (
                                    'day'   => $afterday,
                                    'month' => $aftermonth,
                                    'year'  => $startyear,
                                ),
                                'before'     => array (
                                    'day'   => $beforeday,
                                    'month' => $beforemonth,
                                    'year'  => $currentbefore,
                                ),
                                'inclusive' => true,
                            );
                    }
                }
            } else {
                // they entered only the 'From:' value but make sure it is set to avoid errors
                if (isset($query_args['date_query']['after']) && isset($query_args['date_query']['after']['year'])) {
                    $currentafter = $query_args['date_query']['after']['year'];
                    // if before start date - reset it to the start date but keep the before entry
                    if ($currentafter < $startyear) {
                        print_r("<br/><span style='color: red'>&nbsp;&nbsp;Start date out of range!</span><br/><br/>");
                        $query_args['date_query'] = 
                            array(
                                'after'     => array (
                                    'day'   => $afterday,
                                    'month' => $aftermonth,
                                    'year'  => $startyear,
                                ),
                                'inclusive' => true,
                            );
                   } // no else here - do nothing if the date is in the valid range
                } else {
                    // no year set for some reason
                    $query_args['date_query'] = 
                            array(
                                'after'     => array (
                                    'day'   => $afterday,
                                    'month' => $aftermonth,
                                    'year'  => $startyear,
                                ),
                                'inclusive' => true,
                            );
                }
            }
        }
    }

    return $query_args;
}
add_filter( 'sf_edit_query_args', 'filter_media_release_current_term', 20, 2 );

This successfully filters the results, ensuring no results prior to 1/1/2025 are shown even if they don't filter by date range. However, I had to turn off ajax results so that the page reloads on each submit instead of without reloading because it didn't go through this function with ajax updates. Also, I can't figure out how to update the form or the URL from this function so the page displays "Showing results from [date] to [date]" using the original dates.

How do I apply fix the UI problems?

Thank you for any guidance you can give me.


Solution

  • you're trying to solve a user interface problem with a server-side PHP solution.

    First, you need to add the following code to your theme's functions.php file. This will correctly load our custom JavaScript file.

    function sfp_enqueue_custom_scripts() {
       
        if ( is_search() || is_post_type_archive() || is_page() ) { // Adjust conditions if needed
            wp_enqueue_script(
                'sfp-custom-datepicker',
                get_stylesheet_directory_uri() . '/js/sfp-custom-datepicker.js',
                array( 'jquery', 'jquery-ui-datepicker' ), // Depends on S&F's datepicker
                '1.0.0',
                true // Load in the footer
            );
        }
    }
    add_action( 'wp_enqueue_scripts', 'sfp_enqueue_custom_scripts' );
    

    Next, create a new folder named js inside your active theme's directory. Inside that js folder, create a file named sfp-custom-datepicker.js and paste the following code into it.

    jQuery(document).ready(function($) {
        
        $(document).on("sf:ajaxfinish", ".searchandfilter", function() {
            initialize_custom_datepickers();
        });
    
        initialize_custom_datepickers();
    
        function initialize_custom_datepickers() {
            
            // Form ID 2530 & 2488: Minimum date of Jan 1, 2025
            const minDate2025 = new Date(2025, 0, 1); // Month is 0-indexed (0 = Jan)
    
            // Find the date inputs for these forms.
            // You MUST use your browser's "Inspect Element" tool to find the correct input IDs.
            // They typically look like #_sf_post_date_2530_0 (from) and #_sf_post_date_2530_1 (to).
            const dateFromInput = $('#_sf_post_date_from_id'); // <-- REPLACE with your actual "From" input ID
            const dateToInput = $('#_sf_post_date_to_id'); // <-- REPLACE with your actual "To" input ID
    
            // Check if the search form with ID 2530 or 2488 exists on the page
            if ($('form#sf-form-2530').length || $('form#sf-form-2488').length) {
    
                if (dateFromInput.length) {
                    dateFromInput.datepicker("option", "minDate", minDate2025);
                    dateFromInput.datepicker("option", "changeYear", true);
                    dateFromInput.datepicker("option", "changeMonth", true);
                }
    
                if (dateToInput.length) {
                    dateToInput.datepicker("option", "minDate", minDate2025);
                    dateToInput.datepicker("option", "changeYear", true);
                    dateToInput.datepicker("option", "changeMonth", true);
                }
            }
    
            
        }
    });
    

    Now, replace your complex PHP function with this cleaner, more reliable version.

    function sfp_restrict_by_preset_date( $query_args, $sfid ) {
        // Only run for our target forms
        if ( $sfid != 2530 && $sfid != 2488 ) {
            return $query_args;
        }
    
        // Define the absolute minimum start date for these categories
        $min_start_date = '2025-01-01';
    
        // Check if a user has submitted a 'from' date (_sf_post_date[0])
        if ( isset( $_POST['_sf_post_date'][0] ) && !empty( $_POST['_sf_post_date'][0] ) ) {
            $user_from_date_str = sanitize_text_field( $_POST['_sf_post_date'][0] );
    
            // If the user's chosen start date is before our minimum, override it.
            // strtotime() makes date comparison simple and reliable.
            if ( strtotime( $user_from_date_str ) < strtotime( $min_start_date ) ) {
                // Force the 'after' query to our minimum start date.
                $query_args['date_query']['after'] = array(
                    'year'  => '2025',
                    'month' => '01',
                    'day'   => '01',
                );
            }
        } else {
            // If NO 'from' date is submitted, always enforce the minimum start date.
            $query_args['date_query']['after'] = array(
                'year'  => '2025',
                'month' => '01',
                'day'   => '01',
            );
        }
        
        // Always make the date query inclusive
        if(isset($query_args['date_query'])){
            $query_args['date_query']['inclusive'] = true;
        }
    
        return $query_args;
    }
    add_filter( 'sf_edit_query_args', 'sfp_restrict_by_preset_date', 20, 2 );