One of the little known, but incredibly useful functions of WordPress is wp_cron. It allows you to schedule tasks for execution at a later time, the tasks can also be repeatable. It’s not perfect and does have one serious problem, in that it is only executed while users are actually navigating the site. But on a popular site this won’t make a difference, but it’s still worth noting.
Something I see regularly been asked for is the ability to disable commenting on or delete/hide older posts, generally for more time sensitive posts like competitions or in the case of commerce sites, sale pages. Using the wp_cron and wp_schedule_event functions we will do just that.
Getting started
First we’ll need to an an action hook to execute our function, we do this using the add_action function. We simply specify the name of the action, and the name of the function we want to execute.
add_action( 'hook_for_time_sensitive_posts', 'manage_time_sensitive_posts' );
function manage_time_sensitive_posts() {
}
Next we need to schedule the task, using the wp_schedule_event function, we specify a time (this must be in unix epoch timestamp), the frequency (hourly, twicedaily or daily) and the name of the hook. To get the time we’ll use the current_time function.
add_action( 'hook_for_time_sensitive_posts', 'manage_time_sensitive_posts' );
function manage_time_sensitive_posts() {
}
if ( ! wp_next_scheduled( 'hook_for_time_sensitive_posts' ) ) {
wp_schedule_event( current_time('timestamp'), 'daily', 'hook_for_time_sensitive_posts' );
}
Now that we have a scheduled task, let’s use $wpdb to update older posts and disable comments
Using $wpdb to execute SQL
$wpdb allows you to build a SQL query and execute it. You simply define the SQL statement, specifying the parameter types (%s for strings, %d for decimal numbers and %f for floats) instead of the raw values. It’s a simple and consistent way editing the database in a way that helps prevent mistakes and SQL injection vulnerabilities.
Our first SQL query will disable comments and ping backs on posts older than 31 days. To get the date, we are again going to use the current_time function, but this time we will specify the ‘mysql’ format, and pass in a second parameter to ensure the date is GMT based. We do this as we’re going to use the post_date_gmt column in wp_posts for consistency. The MySQL function DATE_SUB will be used to calculate the date 31 one days ago
$wpdb->query(
$wpdb->prepare( "UPDATE $wpdb->posts SET `comment_status` = %s, `ping_status` = %s WHERE `post_date_gmt` < DATE_SUB(%s, INTERVAL %d DAY);",
array( 'closed', 'closed', current_time('mysql', 1), 31 )
)
);
The second SQL query will mark competition posts as private after 10 days, it follows essentially the same format as above.
$wpdb->query(
$wpdb->prepare( "UPDATE $wpdb->posts SET `post_status` = %s WHERE `post_type` = %s AND `post_date_gmt` < DATE_SUB(%s, INTERVAL %d DAY);",
array( 'private', 'competition', current_time('mysql', 1), 10 )
)
);
And there you have it, a quick and easy way to managed posts and perform periodic activities in WordPress
<?php
add_action( 'hook_for_time_sensitive_posts', 'manage_time_sensitive_posts' );
function manage_time_sensitive_posts() {
global $wpdb;
$wpdb->query(
$wpdb->prepare( "UPDATE $wpdb->posts SET `comment_status` = %s, `ping_status` = %s WHERE `post_date_gmt` < DATE_SUB(%s, INTERVAL %d DAY);",
array( 'closed', 'closed', current_time('mysql', 1), 31 )
)
);
$wpdb->query(
$wpdb->prepare( "UPDATE $wpdb->posts SET `post_status` = %s WHERE `post_type` = %s AND `post_date_gmt` < DATE_SUB(%s, INTERVAL %d DAY);",
array( 'private', 'competition', current_time('mysql', 1), 10 )
)
);
}
if ( ! wp_next_scheduled( 'hook_for_time_sensitive_posts' ) ) {
wp_schedule_event( current_time('timestamp'), 'daily', 'hook_for_time_sensitive_posts' );
}
?>