Skip to content

Instantly share code, notes, and snippets.

@doubleedesign
Last active January 8, 2020 06:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save doubleedesign/4685a0834abf9d5baa1a00ffbb2b1bf9 to your computer and use it in GitHub Desktop.
Save doubleedesign/4685a0834abf9d5baa1a00ffbb2b1bf9 to your computer and use it in GitHub Desktop.
Wordpress Event CPT: Filter archive by ACF date field, with month from and two selected by the user
<?php
/**
* Archive filter queries using the drop-downs on each archive
*
* @see filters.php
* @param $query
*/
function wh_filter_archives($query) {
// Do not modify queries in the admin
if (is_admin() || !$query->is_main_query()) {
return;
}
// Filter by date range (ACF date fields)
$from = (!empty($_REQUEST['from']) ? (string) $_REQUEST['from'] : '');
$to = (!empty($_REQUEST['to']) ? (string) $_REQUEST['to'] : '');
if(!empty($from) && !empty($to)) {
// Build the date meta query
$meta_query[] = array(
'key' => 'event_date',
'compare' => 'BETWEEN',
'type' => 'numeric',
'value' => array($from, $to),
);
// The final query
$query->set('meta_query', array(
'relation' => 'OR',
$meta_query,
$query->get('meta_query'),
));
}
return $query;
}
add_action('pre_get_posts', 'wh_filter_archives', 1);
/**
* Auto-submit archive filters
*/
function initAutoSubmitFilters() {
var filterBar = document.querySelector('.filters');
var filters = document.querySelectorAll('.filters__select__selectbox');
var form = document.getElementById('filter-form');
if((filters != null) && (form != null)) {
for (var i = 0; i < filters.length; i++) {
filters[i].addEventListener('change', function () {
filterBar.classList.add('loading');
form.submit();
});
}
}
}
<?php
/**
* Alternative output of selectboxes on the front-end
* Choose dates grouped by "All", "Next 7 days", "Next 2 weeks", etc
*/
$current_request = $_REQUEST;
?>
<form id="filter-form<?php if(isset($loopcount)){ echo '-'.$loopcount; } ?>" class="filters__select" method="get" action="<?php echo $form_action; ?>" autocomplete="off">
<?php
// Get today's date to calculate the other intervals
$today = date('d-m-Y');
// Calculate the end date of the interval ranges (they will always start from today)
$week = strtotime('+7 day');
$week = date('Ymd', $week);
$fortnight = strtotime('+14 day');
$fortnight = date('Ymd', $fortnight);
$month = strtotime($today . '+1 month');
$month = date('Ymd', $month);
$quarter = strtotime($today . '+3 months');
$quarter = date('Ymd', $quarter);
// Today's date for use by the filter
$today_formatted = date('Ymd');
// Get the last event date, so the "all" option can filter from today until the last date
$range = wh_get_event_date_range();
$last_date = $range['furthest'];
// Build an array of options to build the selectbox
$options = array(
'All' => $last_date,
'Next 7 days' => $week,
'Next 2 weeks' => $fortnight,
'Next month' => $month,
'Next 3 months' => $quarter
);
// Get the current selection so we can make it persistent
$current_selection = $current_request['to'];
?>
<label for="select-start-date" class="filters__select__label">Show me</label>
<span class="filters__select__selectbox-wrapper">
<input type="hidden" name="from" value="<?php echo $today_formatted; ?>">
<select id="select-end-date" name="to" class="filters__select__selectbox">
<?php
foreach($options as $label => $value) {
if (isset($current_selection) && $value == $current_selection) { ?>
<option value="<?php echo $value; ?>" selected="selected"><?php echo $label; ?></option>
<?php } else { ?>
<option value="<?php echo $value; ?>"><?php echo $label; ?></option>
<?php }
} ?>
</select>
</span>
</form>
<?php
/**
* Output selectboxes on the front-end
* to choose dates to filter from and to (by month)
*/
$current_request = $_REQUEST;
?>
<form id="filter-form" class="filters__select" method="get">
<?php
// Get the soonest and furthest event dates from the ACF fields
$date_range = wh_get_event_date_range();
// Get the months and years for the selectbox
$soonest = DateTime::createFromFormat('Ymd', $date_range['soonest']);
$furthest = DateTime::createFromFormat('Ymd', $date_range['furthest']);
$start = ($soonest->modify('first day of this month'));
$end = ($furthest->modify('last day of this month'));
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($start, $interval, $end);
?>
<label for="select-start-date" class="filters__select__label">From</label>
<span class="filters__select__selectbox-wrapper">
<select id="select-start-date" name="from" class="filters__select__selectbox">
<?php
foreach ($period as $date) {
$value = $date->format('Ymd');
$label = $date->format('F Y');
if (isset($current_request['from'] ) && $value == $current_request['from']) { ?>
<option value="<?php echo $value; ?>" selected="selected"><?php echo $label; ?></option>
<?php } else { ?>
<option value="<?php echo $value; ?>"><?php echo $label; ?></option>
<?php } ?>
<?php } ?>
</select>
</span>
<label for="select-end-date" class="filters__select__label">to</label>
<span class="filters__select__selectbox-wrapper">
<select id="select-end-date" name="to" class="filters__select__selectbox">
<?php
foreach ($period as $date) {
$value = $date->format('Ymd');
$value = date('Ymd', strtotime($value. ' + 1 month')); // shift forward to the first of next month so the current month is included
$label = $date->format('F Y');
if (isset($current_request['to'] ) && $value == $current_request['to']) { ?>
<option value="<?php echo $value; ?>" selected="selected"><?php echo $label; ?></option>
<?php } else { ?>
<option value="<?php echo $value; ?>"><?php echo $label; ?></option>
<?php } ?>
<?php } ?>
</select>
</span>
</form>
<?php
/**
* Helper for the events archive filters
* to get the soonest and furthest event dates for use in the filter selections
* Note: This and its uses expect ACF to return YYYYMMDD format (Ymd in PHP)
*
* @return mixed
*/
function wh_get_event_date_range() {
$event_dates = array();
$args = array(
'post_type' => array( 'event' ),
'post_status' => array( 'publish' ),
);
$events = new WP_Query( $args );
if ( $events->have_posts() ) {
while ( $events->have_posts() ) {
$events->the_post();
$event_date = get_field('event_date');
array_push($event_dates, $event_date);
}
}
wp_reset_postdata();
$event_range['soonest'] = min($event_dates);
$event_range['furthest'] = max($event_dates);
return $event_range;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment