Form Scheduling
Core Forms allows you to control when a form accepts submissions using date ranges, day-of-week rules, and time windows. When a form is closed, a customizable message is displayed instead of the form.
Enabling Scheduling
- Open the form editor in WordPress admin.
- Go to the Settings tab.
- Expand the Scheduling section.
- Check Enable scheduling to reveal the configuration options.
Configuration Options
Date Range
Set an open date and/or close date to limit form availability to a specific period.
- Open date: The form becomes available at the start of this day (00:00:00).
- Close date: The form closes at the end of this day (23:59:59).
Either date can be left empty: - No open date = form is available immediately. - No close date = form stays open indefinitely after the open date.
Open date: 2026-05-01
Close date: 2026-05-31
Form is available from May 1 through May 31, 2026.
Day-of-Week Rules
Restrict the form to specific days of the week. Check the days when the form should be open:
| Day | Checkbox |
|---|---|
| Monday | [ ] |
| Tuesday | [ ] |
| Wednesday | [ ] |
| Thursday | [ ] |
| Friday | [ ] |
| Saturday | [ ] |
| Sunday | [ ] |
If no days are checked, the form is available every day (within the date range, if set).
Example: Open Monday through Friday only.
Checked: Mon, Tue, Wed, Thu, Fri
Unchecked: Sat, Sun
Time Window
Set daily open and close times to restrict form availability to specific hours.
- Open time: The time the form opens each day (24-hour format).
- Close time: The time the form closes each day (24-hour format).
Open time: 09:00
Close time: 17:00
Form is available from 9 AM to 5 PM each day.
Overnight Time Windows
The time window supports overnight ranges. When the close time is earlier than the open time, the window wraps around midnight:
Open time: 22:00
Close time: 06:00
Form is available from 10 PM to 6 AM (overnight shift).
Core Forms handles this by checking if the current time is either after the open time OR before the close time.
Timezone
By default, scheduling uses the WordPress site timezone (Settings > General > Timezone). You can override this per form:
Timezone: America/New_York
This ensures the form opens and closes at the correct local time regardless of where the server is located. All timezone identifiers from the IANA database are supported.
If no timezone is set on the form, Core Forms falls back to wp_timezone().
Closed Message
Customize the HTML message displayed when the form is outside its scheduled window:
<div class="cf-form-closed">
<h3>Registration is Currently Closed</h3>
<p>Registration opens on May 1, 2026 at 9:00 AM EST.</p>
<p>Please check back later or <a href="/contact">contact us</a> for more information.</p>
</div>
The default message is: "This form is currently closed for submissions."
You can use template variables in the closed message:
<p>This form opens at {{schedule.open_time}} on {{schedule.next_open_date}}.</p>
Server-Side Validation
Scheduling is enforced on the server, not just the frontend. Even if someone bypasses the frontend closed state (by caching the page or manipulating the DOM), the server rejects submissions when the form is closed.
During Forms::process(), the scheduler check runs before any field validation:
// Simplified server-side check
$scheduler = new FormScheduler();
if (!$scheduler->is_open($form)) {
wp_send_json_error([
'message' => $form->get_closed_message(),
]);
return;
}
The response returns the form's closed message so the frontend can display it.
PHP API: FormScheduler
The FormScheduler class provides a clean API for checking form availability programmatically.
FormScheduler::is_open()
Check if a form is currently accepting submissions:
use Core_Forms\FormScheduler;
$scheduler = new FormScheduler();
$form = cf_get_form('event-registration');
if ($scheduler->is_open($form)) {
echo 'Form is accepting submissions.';
} else {
echo $form->get_closed_message();
}
FormScheduler::get_schedule()
Retrieve the full schedule configuration for a form:
$schedule = $scheduler->get_schedule($form);
// Returns:
[
'enabled' => true,
'open_date' => '2026-05-01',
'close_date' => '2026-05-31',
'days' => ['mon', 'tue', 'wed', 'thu', 'fri'],
'open_time' => '09:00',
'close_time' => '17:00',
'timezone' => 'America/New_York',
'closed_msg' => 'Registration is currently closed.',
]
FormScheduler::next_open()
Get the next date/time the form will be open (useful for displaying countdown timers or next-open messages):
$next = $scheduler->next_open($form);
if ($next) {
echo 'Form opens again: ' . $next->format('F j, Y \a\t g:i A T');
// Output: "Form opens again: May 3, 2026 at 9:00 AM EDT"
} else {
echo 'Form will not open again (past close date).';
}
Returns a DateTimeImmutable object in the form's configured timezone, or null if the form will not reopen.
Evaluation Logic
The scheduler evaluates conditions in this order:
- Date range check: Is today within the open/close date range?
- Day-of-week check: Is today an allowed day?
- Time window check: Is the current time within the open/close time window?
All three must pass for the form to be open. If scheduling is not enabled, the form is always open.
// Pseudocode for the evaluation logic
function is_open($form) {
$schedule = $this->get_schedule($form);
if (!$schedule['enabled']) {
return true;
}
$now = new DateTimeImmutable('now', new DateTimeZone($schedule['timezone']));
// 1. Date range
if ($schedule['open_date'] && $now < $schedule['open_date']) {
return false;
}
if ($schedule['close_date'] && $now > $schedule['close_date_end_of_day']) {
return false;
}
// 2. Day of week
if (!empty($schedule['days'])) {
$today = strtolower($now->format('D'));
if (!in_array($today, $schedule['days'])) {
return false;
}
}
// 3. Time window
if ($schedule['open_time'] && $schedule['close_time']) {
$current_time = $now->format('H:i');
if ($schedule['close_time'] < $schedule['open_time']) {
// Overnight window
if ($current_time < $schedule['open_time'] && $current_time > $schedule['close_time']) {
return false;
}
} else {
// Normal window
if ($current_time < $schedule['open_time'] || $current_time > $schedule['close_time']) {
return false;
}
}
}
return true;
}
Examples
Event Registration (Fixed Dates)
{
"settings": {
"scheduling": {
"enabled": true,
"open_date": "2026-04-15",
"close_date": "2026-05-01",
"timezone": "America/Chicago",
"closed_message": "<p>Registration for the 2026 conference opens April 15.</p>"
}
}
}
Business Hours Form
{
"settings": {
"scheduling": {
"enabled": true,
"days": ["mon", "tue", "wed", "thu", "fri"],
"open_time": "08:30",
"close_time": "17:30",
"timezone": "Europe/London",
"closed_message": "<p>Our support form is available Monday-Friday, 8:30 AM - 5:30 PM GMT.</p>"
}
}
}
Night Shift Application
{
"settings": {
"scheduling": {
"enabled": true,
"days": ["mon", "tue", "wed", "thu", "fri", "sat", "sun"],
"open_time": "22:00",
"close_time": "06:00",
"timezone": "America/New_York",
"closed_message": "<p>Night shift applications are accepted between 10 PM and 6 AM.</p>"
}
}
}
Hooks
Filter the schedule before evaluation:
// Override schedule for a specific form
add_filter('cf_form_schedule', function ($schedule, $form) {
if ($form->slug === 'holiday-contest') {
$schedule['close_date'] = '2026-12-25';
}
return $schedule;
}, 10, 2);
Action fired when a submission is blocked by the scheduler:
add_action('cf_submission_blocked_by_schedule', function ($form, $schedule) {
// Log or notify
error_log("Submission blocked for form {$form->slug} - outside schedule.");
}, 10, 2);