Scheduling Events with WordPress Tutorial

Standard

There are many reasons to schedule events; maybe you need to check an external API, or prehaps periodically empty a cache. This process can even be used for something as simple as making a post un-sticky after a certain length of time.

Scheduling Events in WordPress is basically running a Cron, just simplified by WP. There are several functions available as tools for this process, and here we’re going to take a look at three of them:

In the code at the bottom of this post is a plugin that you can insert into your wp_content/plugins folder. It will produce an admin menu item entitled “Schedule Event Tutorial.” This plugin is very simple: You check a checkbox and set a time for it to become unchecked. After that time has passed, the checkbox will become unchecked.

Screen Shot 2013-11-11 at 10.23.07 PM

The Process

The way the plugin works is that when the checkbox is checked and a time is selected, a function is run that does two things:

1. Checks to see if another “unchecking” event is already scheduled. If so, it removes that event.

2. Schedules the new “unchecking” event.

How it Works

First of all, The actual unchecking is done by the function uncheck_checkbox(). You will see around line 44 that we have hooked that function into the action we’re calling ‘uncheck_event_hook’.

This is just like any other add_action(). The array(__CLASS__….) part is a part of the Object-Oriented Programming we’re using. It tells the add_action function that we’re referencing a method (funciton) inside this class.

add_action( 'uncheck_event_hook', array( __CLASS__, 'uncheck_checkbox' ) );

The interesting part is teling ‘uncheck_event_hook’ when to fire.

Now, follow along in the schedule_event() function…

First, check to make sure process only runs if the “Save Changes” button has been pressed.

if ( ! isset( $_GET['settings-updated'] ) )
    return;

Then a check is run to see if an event exists on this hook. It gets the next time this hook is scheduled to fire by using wp_next_scheduled. Then, if any value is returned, wp_unschedule_event is used to unschedule that event from the ‘uncheck_event_hook’.

// Remove any scheduled event on this hook
    $scheduled_event = wp_next_scheduled( 'uncheck_event_hook' );
    if ( $scheduled_event !== false ) {
        wp_unschedule_event( $scheduled_event, 'uncheck_event_hook' );
    }

Next, we do the actual scheduling. We grab the value of our expiration time setting, and if it’s a number, we set the time the ‘uncheck_event_hook’ will run.

// Schedule the event to uncheck the checkbox
    $exp_time = self::expiration_time();
    if ( is_numeric( $exp_time ) ) {
        wp_schedule_single_event( $exp_time, 'uncheck_event_hook' );
    }

At this point, we wait until the time passes our expiration time, then on the next time any page is viewed on your site, the ‘uncheck_event_hook’ will fire off uncheck_checkbox(), as we set in the add_action() at the beginning of the process.

The Full Plugin Code

I decided to write this as a fully-featured plugin for a few reasons:

  1. An installable plugin would help make this process a bit more practical
  2. I learn best by viewing others’ code. Maybe you can learn something new by looking at how another developer does it

By presenting the full code, less-experienced developers have the chance to learn more about Object-Oriented code, as well as what it takes to set up a Plugin. Of course, if you have any questions about what’s going on, be sure to hit me up. I’d love to help you on your way to learning something new!

<?php
/**
* Plugin Name: Schedule Event Tutorial
* Description: Schedules single event to uncheck a checkbox on a custom Menu page
* Version: 0.1
* Author: John Regan
* Author URI: http://johnregan3.me
* Text Domain: setjr3
* License: GPLv2+
*/
/**
* Copyright (c) 2013 X-Team (http://x-team.com/)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License, version 2 or, at
* your discretion, any later version, as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* This class is where you can see Scheduled Events in action.
*
* Here, the old scheduled event is unscheduled and the new event is set.
*/
class Schedule_Event_Tutorial {
/**
* Registers our 'uncheck_event_hook" action hook that fires our un-checking action.
*/
static function setup() {
// Scheduled Event Hook
add_action( 'uncheck_event_hook', array( __CLASS__, 'uncheck_checkbox' ) );
}
/**
* On settings save, Update scheduled event time.
*
* Begin by removing any scheduled event on our 'uncheck_event_hook' hook.
* Then, we format the saved time to Unix.
* Finally, we schedule the event.
*
* Typically, this could be fired when a post is saved ('save_post' hook, for instance),
* but it's not really that easy on an options page like this one.
*
* @action 'load-{page}'
* See Schedule_Event_Tutorial_Setup::menu_page()
*/
static function schedule_event() {
if ( ! isset( $_GET['settings-updated'] ) )
return;
// Remove any scheduled event on this hook
$scheduled_event = wp_next_scheduled( 'uncheck_event_hook' );
if ( $scheduled_event !== false ) {
wp_unschedule_event( $scheduled_event, 'uncheck_event_hook' );
}
// Schedule the event to uncheck the checkbox
$exp_time = self::expiration_time();
if ( is_numeric( $exp_time ) ) {
wp_schedule_single_event( $exp_time, 'uncheck_event_hook' );
}
}
/**
* Fetches and formats the saved expiration time
*
* Get expiration time from options, set it according to the local timezone
* then format it as Unix time.
*
* @return int $time Unix-formatted time string
*/
static function expiration_time() {
$exp_time = get_option( 'setjr3_time' );
$time = ( ! empty( $exp_time ) ) ? $exp_time : null ;
// If no time is set, exit.
if ( is_null( $time ) )
return false;
$tz_local = new DateTimeZone( get_option( 'timezone_string' ) );
$time = new DateTime( $time, $tz_local );
$time = (int)$time->format('U');
return $time;
}
/**
* The actual un-checking of the checkbox
*
* Fires on 'uncheck_event_hook' action, set in setup() above.
*
* @action 'uncheck_event_hook'
*/
static function uncheck_checkbox() {
update_option( 'setjr3_checkbox', null );
}
} // End class Schedule_Event_Tutorial
/**
* Set up the Tutorial
*
* The content of this class simply sets up the tutorial form.
* If you find it confusing, just ignore it.
*/
class Schedule_Event_Tutorial_Setup {
/**
* Add our actions/filter
*/
static function setup() {
$plugin = plugin_basename(__FILE__);
add_filter( "plugin_action_links_$plugin", array( __CLASS__, 'tutorial_link' ) );
// add action for Menu page
add_action( 'admin_menu', array( __CLASS__, 'menu_page' ) );
// add action for Settings
add_action( 'admin_init', array( __CLASS__, 'settings' ) );
// Run our Schedule_Event_Tutorial class above
Schedule_Event_Tutorial::setup();
// Clean up when this plugin is uninstalled
register_uninstall_hook( __FILE__, array( __CLASS__, 'uninstall' ) );
}
/**
* Print direct link to Tutorial Admin Page
*
* Fetches array of links generated by WP Plugin admin page ( Deactivate | Edit )
* and inserts a link to the Custom CSS admin page
*
* @param array $links Array of links generated by WP in Plugin Admin page.
* @return array $links Array of links to be output on Plugin Admin page.
*/
static function tutorial_link( $links ) {
$settings_page = '<a href="' . admin_url( 'admin.php?page=schedule-event-tutorial.php' ) .'">Tutorial</a>';
array_unshift( $links, $settings_page );
return $links;
}
/**
* Create Admin Menu Page
*
* Also fires action to Schedule the Event when page reloads.
* see Schedule_Event_Tutorial::schedule_event()
*/
static function menu_page() {
$slug = add_menu_page( __( 'Schedule Event Tutorial', 'setjr3' ), __( 'Schedule Event Tutorial', 'setjr3' ), 'manage_options', basename(__FILE__), array( __CLASS__, 'render_tutorial_page' ) );
add_action( 'load-' . $slug, array( 'Schedule_Event_Tutorial', 'schedule_event' ) );
}
/**
* Settings Page setup
*
* For more info: http://codex.wordpress.org/Settings_API
*/
static function settings() {
register_setting( 'setjr3_settings_group', 'setjr3_checkbox' );
register_setting( 'setjr3_settings_group', 'setjr3_time' );
add_settings_section( 'setjr3_section', '', '', __FILE__ );
add_settings_field( 'checkbox', __( 'Checkbox', 'setjr3' ), array( __CLASS__, 'checkbox' ), __FILE__, 'setjr3_section' );
add_settings_field( 'expiration_time', __( 'Expiration Time', 'setjr3' ), array( __CLASS__, 'expiration_time' ), __FILE__, 'setjr3_section' );
}
/**
* Render Checkbox
*/
static function checkbox() {
$checkbox_value = get_option( 'setjr3_checkbox' );
echo '<input type="checkbox" name="setjr3_checkbox" value="1" ' . checked( 1, $checkbox_value, false ) . '/>&nbsp;&nbsp;<span class="description">This checkbox will uncheck after the expiration time set below.</span>';
}
/**
* Render Date Input
*/
static function expiration_time() {
$exp_time = get_option( 'setjr3_time' );
$exp_time_value = ( ! empty( $exp_time ) ) ? $exp_time : substr_replace( current_time( 'mysql' ), 'T', 10, 1 ) ;
echo '<input name="setjr3_time" type="datetime-local" value="' . $exp_time_value .'" step="1" />';
}
/**
* Render Menu Page
*/
static function render_tutorial_page() {
$curr_time = substr_replace( current_time( 'mysql' ), 'T', 10, 1 );
$exp_time = get_option( 'setjr3_time' );
$exp_time_value = ( ! empty( $exp_time ) ) ? $exp_time : 'Not set' ;
?>
<div class="wrap">
<h2><?php echo __( 'Schedule Event Tuorial', 'setjr3') ?></h2>
<?php if ( isset( $_GET['settings-updated'] ) ) { ?>
<div id="message" class="updated">
<p><strong><?php _e( 'Settings saved.', 'setjr3' ) ?></strong></p>
</div>
<?php } ?>
<p>
<?php _e( 'This is a tutorial demonstrating how to Schedule Events.<br />Begin by checking the checkbox below, then set a time for the checkbox to become unchecked.<br />Then, on the next page refresh after that time, the checkbox will be unchecked.', 'setjr3' ) ?>
</p>
<p>
<code><?php _e( 'Current Time', 'setjr3' ) ?>: <?php echo $curr_time ?></code><br />
<code><?php _e( 'Uncheck Time', 'setjr3' ) ?>: <?php echo $exp_time_value ?></code>
</p>
<form method="post" action="options.php" enctype="multipart/form-data">
<?php settings_fields( 'setjr3_settings_group' ) ?>
<?php do_settings_sections( __FILE__ ) ?>
<?php submit_button() ?>
</form>
</div>
<?php
}
/**
* Cleanup on unistnall
*/
static function uninstall() {
unregister_setting( 'setjr3_settings_group', 'setjr3_checkbox' );
unregister_setting( 'setjr3_settings_group', 'setjr3_time' );
}
}
add_action( 'plugins_loaded', array( 'Schedule_Event_Tutorial_Setup', 'setup' ) );