Delete posts from a post type automatically via Cron

Although I do not understand the motivation for truncating posts, I think this exercise is valuable for you to understand how to use cron + WordPress.

Create a function to truncate posts

This can be used for both methods below WP-cron or UNIX cron.

function foobar_truncate_posts(){
    global $wpdb;

    # Set your threshold of max posts and post_type name
    $threshold = 50;
    $post_type="foobar";

    # Query post type
    $query = "
        SELECT ID FROM $wpdb->posts 
        WHERE post_type="$post_type" 
        AND post_status="publish" 
        ORDER BY post_modified DESC
    ";
    $results = $wpdb->get_results($query);

    # Check if there are any results
    if(count($results)){
        foreach($result as $post){
            $i++;

            # Skip any posts within our threshold
            if($i <= $threshold)
                continue;

            # Let the WordPress API do the heavy lifting for cleaning up entire post trails
            $purge = wp_delete_post($post->ID);
        }
    }
}

Here are the two basic approaches to scheduling events in WordPress.

Approach #1: Using WP-Cron

Since this is the WP way of doing this, we’ll look at this approach first. Please note, WP Cron is not true cron, and it’s oft called psuedo-cron. It is not consistent if you have low traffic on a site as it is based on requests to the server. If no requests come in, then your scheduled event runs late.

Schedule your event

if(!wp_next_scheduled( 'foobar_truncate_posts_schedule')){
    wp_schedule_event(time(), 'daily', 'foobar_truncate_posts_schedule');
}

Hook into your schedule action

add_action('foobar_truncate_posts_schedule', 'foobar_truncate_posts');

If you find that WP-Cron is missing your schedule, publishing scheduled posts, etc…, you can automate it further with a UNIX cron. Here’s a great article to show you how to ping wp-cron.php at specified intervals. Here’s what they recommend to keep wp-cron on-time using a UNIX cron.

wget http://www.server.com/wp-cron.php > /dev/null 2>&1

Approach #2: Using a UNIX cron

You can use true UNIX crons with native admin-ajax.php functionality.

Verify cURL on your server

This approach uses cURL which should be installed on your server. If not and you’re using Apache, sudo apt-get install php5-curl and then sudo /etc/init.d/apache2 restart.

Create an AJAX hook

Make sure to set it to nopriv as your server wont be authenticating with WP.

add_action('wp_ajax_nopriv_truncate_posts', 'foobar_truncate_posts_cron');
function foobar_truncate_posts_cron(){

    # We use the user-agent as a shared key
    $shared_user_agent="FooBar TruncatePostsCron/1.0";

    # Block unwanted IP addresses
    $whitelisted_ips = array( //IPs allowed to run this operation
        '192.168.1.1',
        '127.0.0.1'
    );

    # Retrive Request Information
    $request_user_agent = $_SERVER['HTTP_USER_AGENT'];
    $request_ip = $_SERVER['REMOTE_ADDR'];


    # Authenticate
    if($request_user_agent === $shared_user_agent && in_array($request_ip, $whitelisted_ips))
        echo foobar_truncate_posts(); // Reusable function
    else
        echo 'Authentication failed for post trucation cron.';

    exit;
}

Add your Crontab

This config will run one time per day consistently. -A sets the shared user agent secret -o specifies an output file, action=truncate_posts is relative to your ajax hook action. Verify /user/bin/curl is a proper path for executing a cURL command. You might be able to just use curl instead.

0 0 * * * /usr/bin/curl -A 'FooBar TruncatePostsCron/1.0' -o ~/truncate_posts.log http://yourdomain.com/wp-admin/admin-ajax.php?action=truncate_posts

And finally, always make sure you set register_globals=off in your php.ini to prevent spoofing of any sort.

And, Finally…

These are the two main approaches to WordPress + cron (whether true or not). There are many ways to skin a cat with your specific use case in foobar_truncate_posts(). I’m sure you can tweak it from here. Hope this helps you out!

Leave a Comment