While talking to Amanda who’s website I build over at Authentic Alignment Wellness we discussed how it would be nice to show off upcoming events with as little effort as possible on her end.
This requires a few steps
- Easy event setup on the wordpress backend
- Only the next event upcoming is shown off
- If no events are upcoming show a default placeholder
Custom Post Type
I didn’t want events to be posts I wanted them to be events so I dropped in a custom post type into my functions.php file
function wporg_custom_post_type()
{
register_post_type('flaxen_event',
array(
'labels' => array(
'name' => __('Events'),
'singular_name' => __('Events'),
),
'public' => true,
'has_archive' => true,
'rewrite' => array( 'slug' => 'events' ),
)
);
}
add_action('init', 'wporg_custom_post_type');
Meta Dates
Custom post types are still using the classic wordpress editor so I had to add meta boxes the old way, this is a pretty big block of code so I’ll break it up into manageable chunks but this all goes into the functions.php file or a required file from it
Register the Meta Boxes
function event_date_add_post_meta_boxes() {
add_meta_box(
'event-date', // Unique ID
'Event Date', // Title
'event_date_render_metabox', // Callback function
'flaxen_event', // post
'normal', // Context
'default' // Priority
);
}
add_action( 'add_meta_boxes', 'event_date_add_post_meta_boxes' );
Defaults
function event_date_defaults() {
return array(
'start_date_m' => 'default',
'start_date_d' => 'default',
'start_date_o' => 'default',
'end_date_m' => 'default',
'end_date_d' => 'default',
'end_date_o' => 'default',
);
}
Render the meta box
function event_date_render_metabox() {
// Variables
global $post; // Get the current post data
$saved = get_post_meta( $post->ID, 'event_date', true ); // Get the saved values
$defaults = event_date_defaults(); // Get the default values
$event_date = wp_parse_args( $saved, $defaults ); // Merge the two in case any fields don't exist in the saved data
?>
Create the inputs
Start with an opening and a variable for the current month
<fieldset>
<div class="wrap">
<?php $em = date("m"); ?> <!-- used with an if this month is -->
<p>When does this event start.</p>
The Month
<select id="event_date[start_date_m]" name="event_date[start_date_m]">
<!-- check if there has been a month set and its this month else if month has not been set but its currently this month then its also selected -->
<option value="01" <?php if ( $event_date['start_date_m'] == '01' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 1) { echo "selected"; } ?>>01-Jan</option>
<option value="02" <?php if ( $event_date['start_date_m'] == '02' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 2) { echo "selected"; } ?>>02-Feb</option>
<option value="03" <?php if ( $event_date['start_date_m'] == '03' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 3) { echo "selected"; } ?>>03-Mar</option>
<option value="04" <?php if ( $event_date['start_date_m'] == '04' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 4) { echo "selected"; } ?>>04-Apr</option>
<option value="05" <?php if ( $event_date['start_date_m'] == '05' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 5) { echo "selected"; } ?>>05-May</option>
<option value="06" <?php if ( $event_date['start_date_m'] == '06' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 6) { echo "selected"; } ?>>06-Jun</option>
<option value="07" <?php if ( $event_date['start_date_m'] == '07' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 7) { echo "selected"; } ?>>07-Jul</option>
<option value="08" <?php if ( $event_date['start_date_m'] == '08' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 8) { echo "selected"; } ?>>08-Aug</option>
<option value="09" <?php if ( $event_date['start_date_m'] == '09' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 9) { echo "selected"; } ?>>09-Sep</option>
<option value="10" <?php if ( $event_date['start_date_m'] == '10' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 10) { echo "selected"; } ?>>10-Oct</option>
<option value="11" <?php if ( $event_date['start_date_m'] == '11' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 11) { echo "selected"; } ?>>11-Nov</option>
<option value="12" <?php if ( $event_date['start_date_m'] == '12' ) { echo "selected"; } elseif ( $event_date['start_date_m'] == 'default ' && $em == 12) { echo "selected"; } ?>>12-Dec</option>
</select>
The Day and Year
<input id="event_date[start_date_d]" name="event_date[start_date_d]" type="text" size="2" maxlength="2" autocomplete="off" value="<?php if ($event_date['start_date_d'] != 'default') { echo $event_date['start_date_d']; } else { echo date("d"); } ?>">
,
<input id="event_date[start_date_o]" name="event_date[start_date_o]" type="text" size="4" maxlength="4" autocomplete="off" value="<?php if ($event_date['start_date_o'] != 'default') { echo $event_date['start_date_o']; } else { echo date("o"); } ?>">
</div>
Repeat for end dates
But then also close up with a nonce for security
<div class="wrap">
<?php $tomorrow = date("d") + 1; ?>
<p>When does this event finish.</p>
<select id="event_date[end_date_m]" name="event_date[end_date_m]">
<option value="01" <?php if ( $event_date['end_date_m'] == '01' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 1) { echo "selected"; } ?>>01-Jan</option>
<option value="02" <?php if ( $event_date['end_date_m'] == '02' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 2) { echo "selected"; } ?>>02-Feb</option>
<option value="03" <?php if ( $event_date['end_date_m'] == '03' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 3) { echo "selected"; } ?>>03-Mar</option>
<option value="04" <?php if ( $event_date['end_date_m'] == '04' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 4) { echo "selected"; } ?>>04-Apr</option>
<option value="05" <?php if ( $event_date['end_date_m'] == '05' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 5) { echo "selected"; } ?>>05-May</option>
<option value="06" <?php if ( $event_date['end_date_m'] == '06' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 6) { echo "selected"; } ?>>06-Jun</option>
<option value="07" <?php if ( $event_date['end_date_m'] == '07' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 7) { echo "selected"; } ?>>07-Jul</option>
<option value="08" <?php if ( $event_date['end_date_m'] == '08' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 8) { echo "selected"; } ?>>08-Aug</option>
<option value="09" <?php if ( $event_date['end_date_m'] == '09' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 9) { echo "selected"; } ?>>09-Sep</option>
<option value="10" <?php if ( $event_date['end_date_m'] == '10' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 10) { echo "selected"; } ?>>10-Oct</option>
<option value="11" <?php if ( $event_date['end_date_m'] == '11' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 11) { echo "selected"; } ?>>11-Nov</option>
<option value="12" <?php if ( $event_date['end_date_m'] == '12' ) { echo "selected"; } elseif ( $event_date['end_date_m'] == 'default ' && $em == 12) { echo "selected"; } ?>>12-Dec</option>
</select>
<input id="event_date[end_date_d]" name="event_date[end_date_d]" type="text" size="2" maxlength="2" autocomplete="off" value="<?php if ($event_date['end_date_d'] != 'default') { echo $event_date['end_date_d']; } else { echo $tomorrow; } ?>">
,
<input id="event_date[end_date_o]" name="event_date[end_date_o]" type="text" size="4" maxlength="4" autocomplete="off" value="<?php if ($event_date['end_date_o'] != 'default') { echo $event_date['end_date_o']; } else { echo date("o"); } ?>">
</div>
</fieldset>
?php
// This validates that submission came from the actual dashboard and not the front end or a remote server.
wp_nonce_field( 'event_date_metabox_nonce', 'event_date_metabox_process' );
}
Save the Metabox
function event_date_save_metabox( $post_id, $post ) {
// Verify that our security field exists. If not, bail.
if ( !isset( $_POST['event_date_metabox_process'] ) ) return;
// Verify data came from edit/dashboard screen
if ( !wp_verify_nonce( $_POST['event_date_metabox_process'], 'event_date_metabox_nonce' ) ) {
return $post->ID;
}
if ( !isset( $_POST['event_date'] ) ) {
return $post->ID;
}
// Verify user has permission to edit post
if ( !current_user_can( 'edit_post', $post->ID )) {
return $post->ID;
}
$sanitized = array();
// Loop through each of our fields
foreach ( $_POST['event_date'] as $key => $date ) {
// Sanitize the data and push it to our new array
// `wp_filter_post_kses` strips our dangerous server values
// and allows through anything you can include a post.
$sanitized[$key] = wp_filter_post_kses( $date );
}
// Save our submissions to the database
update_post_meta( $post->ID, 'event_date', $sanitized );
}
add_action( 'save_post', 'event_date_save_metabox', 1, 2 );
By this point we have a custom post type on the backend where we can add start and end dates to the custom meta boxes that will save and we can return to them
Create an array with IDs and dates
Now I loop the latest ten events and build an array with that info but I don’t write anything to the page so I suggest putting this right above where it will be implemented, in my case the header.php file.
<?php
$date_now = new DateTime(); // current time date, note this cant be used with an echo $date_now needs print_r($date_now);
$stack = array(); // build an empty array to add event dates to
// query for events
$args = [
'post_type' => 'flaxen_event',
'posts_per_page' => 10,
];
// run the events in a loop this doesnt print anything just builds an array
$loop = new WP_Query($args);
while ($loop->have_posts()) {
$loop->the_post();
$meta = get_post_meta( $post->ID, 'event_date', false ); // grab the dates meta
$data = $meta[0]; // this ends up as an array in an array it might be possible to remove this step but for now its needed
// create variables for the date portions
$mon = $data['start_date_m'];
$da = $data['start_date_d'];
$yea = $data['start_date_o'];
// create a date with the variables as one
$eventdate = new DateTime("$mon/$da/$yea"); // runs month / day / year 13/12/2016
$event_id = get_the_id();
$stack[$event_id] = $eventdate; // add the dates as a value to the array with the ID as the key
} // while have events
Sort the stack
There are a number of ways of sorting arrays in php the one I am using here is sort as it orders the values without resetting the keys
asort($stack); // ascending sort is oldest to newest and doesnt alter the keys
Print the next event
At this point we have everything in order we just need to print the title of the upcoming event
foreach ( $stack as $key => $value ) {
if ($date_now < $value) {
$title = get_post($key)->post_title; // the events title
?>
<p><?php echo $title; ?></p>
<?php break; // stop looping once we find something in the future
} // if the events in the future
} // loop of all events
If no upcoming events
We need to have the fallback incase we don’t have an event coming up
$last = array_key_last ($stack);
if ($date_now > $stack[$last]) { ?>
<p>Start With a Free Discovery Session</p>
<?php } ?>