WPForms – Dynamic availability in booking form

I built an online booking form using WPForms that allowed customers to select from a list of available days/times.

There’s a few components you need:

  1. Client editable list of available days/times
  2. List of days already booked / manually added “unavailable” times
  3. Dynamically generate a list of available times by comparing the two.

I added a settings page to the form for specifying general availability (ex: Monday at 7:30am) and to edit a list of unavailable day/times (ex: Monday, January 28 at 7:30am). When the form is submitted, the selected date is automatically added to the unavailable day/times.

We’re using the wpforms_field_data filter to update a dropdown field with the available options. We identify the correct select field by looking for a custom CSS class of dynamic-booking-times.

We use the list of general availability to build a list of the actual days/times available from now until 60 days out. We then remove any day/times that are already booked.

<?php /** * Core Functionality Plugin * * @package CoreFunctionality * @since 1.0.0 * @copyright Copyright (c) 2014, Bill Erickson & Jared Atchison * @license GPL-2.0+ */ function ea_booking_field_dropdown( $field, $form_data ) { if( 'select' !== $field['type'] ) return $field; $classes = explode( ' ', $form_data['fields'][ $field['id'] ]['css'] ); if( ! in_array( 'dynamic-booking-times', $classes ) ) return $field; $field['choices'] = ea_get_available_booking_times( $form_data ); return $field; } add_filter( 'wpforms_field_data', 'ea_booking_field_dropdown', 20, 2 ); /** * Get Available Booking Times * */ function ea_get_available_booking_times( $form_data = array() ) { $start = strtotime( $form_data['settings']['mct_book_before'], current_time( 'timestamp' ) ); $end = strtotime( $form_data['settings']['mct_book_after'], current_time( 'timestamp' ) ); $availability = explode( PHP_EOL, $form_data['settings']['mct_general_availability'] ); $days = array(); foreach( $availability as $option ) { $option = explode( ' at ', $option ); $days[$option[0]][] = $option[1]; } $options = array(); for( $current = $start; $current < $end; $current += DAY_IN_SECONDS ){ $day = date( 'l', $current ); if( isset( $days[$day] ) ) { foreach( $days[$day] as $time ) { $daytime = strtotime( date( 'l, F j, Y', $current ) . ' ' . $time ); if( $daytime < $end && $daytime > $start ) $options[] = array( 'label' => date( 'l, F j, Y', $daytime ) . ' at ' . date( 'g:ia', $daytime ), 'value' => $daytime ); } } } $booked = explode( PHP_EOL, $form_data['settings']['mct_booked_times'] ); if( !empty( $booked ) ) { foreach( $booked as $booked_time ) { $booked_time = strtotime( str_replace( ' at ', ' ', $booked_time ) ); foreach( $options as $i => $option ) { if( $option['value'] == $booked_time ) { unset( $options[$i] ); } } } } return $options; } /** * Update list of booked times on form completion * */ function ea_update_list_of_booked_times( $fields, $entry, $form_data, $entry_id ) { $booked = explode( PHP_EOL, $form_data['settings']['mct_booked_times'] ); $booked[] = $fields[2]['value']; $form_data['settings']['mct_booked_times'] = implode( PHP_EOL, array_filter( $booked ) ); wpforms()->form->update( EA_BOOKING_FORM_ID, $form_data ); } add_action( 'wpforms_process_complete_' . EA_BOOKING_FORM_ID, 'ea_update_list_of_booked_times', 10, 4 ); /** * Delete past bookings * */ function ea_delete_past_bookings() { $last_updated = get_option( 'mct_updated_bookings_list' ); if( ! $last_updated || $last_updated < strtotime( '-24 hours' ) ) { $form = wpforms()->form->get( EA_BOOKING_FORM_ID ); $form_data = wpforms_decode( $form->post_content ); $booked = explode( PHP_EOL, $form_data['settings']['mct_booked_times'] ); foreach( $booked as $i => $datetime ) { if( !empty( $datetime ) ) { $datetime = str_replace( ' at ', ' ', $datetime ); if( strtotime( $datetime ) < current_time( 'timestamp' ) ) { unset( $booked[$i] ); } } } $form_data['settings']['mct_booked_times'] = implode( PHP_EOL, array_filter( $booked ) ); wpforms()->form->update( EA_BOOKING_FORM_ID, $form_data ); update_option( 'mct_updated_bookings_list', time() ); } } add_action( 'shutdown', 'ea_delete_past_bookings' );

Bill Erickson

Bill Erickson is a freelance WordPress developer and a contributing developer to the Genesis framework. For the past 14 years he has worked with attorneys, publishers, corporations, and non-profits, building custom websites tailored to their needs and goals.

Ready to upgrade your website?

I build custom WordPress websites that look great and are easy to manage.

Let's Talk