Delete posts from a post type automatically via Cron

how can I use Cron to delete posts of a certain post type once they reach a certain limit, like keep maximum 50 posts?

The reason is that these posts are being imported automatically periodically, so I want to prevent the DB getting too large, apart from the fact that the older posts won’t be needed.

Related posts

Leave a Reply

2 comments

  1. 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!

  2. The most solid method would be to use WP-Cron itself. But if you have a very light reqirement, you can leave it as such and no issues like multiple visits tiggering the wp-cron multiple times and events overlapping will never occur.

    Should refer to Is it safe to run wp-cron.php twice if the first instance takes too long?

    It is clearly stated there ( actually the answer which deserves more votes ) has the statement in the thrid paragraph “because wp-cron reschedules and unschedules jobs as it goes. Right before it runs a job, it unschedules it. This prevents the job from running twice”, yes there are apprehensions that there may be a race condition that might occur where a heavy bogged blog might kick the same event twice.

    Now the wordpress team has a solution for the same, and that is to disable the cron in the wp-config.php. This does not disable cron, but actually disables the firing of cron when a visit occurs. After this a web cron can be setup using wget or curl but if we are not confident that services will finish inside 30 seconds, which happens to be the default timeout for a php script, then the cron should be set up on the server itself using the php cli. A more indepth document on how to do this is available at https://rtcamp.com/tutorials/wordpress/wp-cron-crontab/