Keep a fluid max number of posts on site

Here is an idea but before we go into details, here are VERY VERY IMPORTANT notes

NOTE: READ THIS FIRST

  • Take a database back up before running this code. It is advisable to run this on a local install first for testing purposes.

  • Note on wp_trash_post(), from the codex

    If trash is disabled, the post or page is permanently deleted.

  • I have tested the code, and it works. You can however make changes to it to suite your needs. As it stands, the code should only delete posts when a new post is published

WORKSFLOW

What we need to do is

  • Run a custom function to delete posts when ever a new post is published. For this, we will use the transition_post_status hook. Just one note, this hook fires when a post is published, trashed, updated and untrashed. We will need to restrict our custom function to only run when a post is published. This line, if ( $new_status == 'publish' && $old_status != 'publish' ) will take care of that

  • Use get_posts() to get all the published posts. You can adjust this to suite your needs. We only need the post ids, so this is what we will get. It makes the query really fast and does not eat up resources

  • The returned array of posts from get_posts() needs to be counted, and if there are more than a 1000 posts, we need to get the post ids after the first thousand posts. we will use array_slice here

  • We need to run wp_trash_post if we have more than 1000 posts to trash these posts. If you need to delete everything attached to the post as well, you can use wp_delete_post here instead of wp_trash_post. You can just uncomment this line, wp_delete_post( $trash_post ); in the code and comment this line out wp_trash_post( $trash_post );. Do not run both at the same time

PUTTING IT INTO CODE

The code is well commented as well, so it will be easy to follow. Just one note, you will need a minimum of PHP5.4+ installed on your server due to the use of new array syntax. Also note, closures needs a minimum of PHP5.3

add_action( 'transition_post_status', function ( $new_status, $old_status, $post )
{
    // Run this only when a new post is publish to save on unnecessary waste of resources
    if ( $new_status == 'publish' && $old_status != 'publish' ) {
    
        /*
         * Use get_posts() to count all the posts published, get only post ids to improve performance
         * This array of post ids will also be used to get the post ids of posts to be trashed
         */
        $total_posts = get_posts( ['posts_per_page' => -1, 'fields' => 'ids'] );
        // Count the amount of posts in the returned array from get_posts
        $count = count( $total_posts );
        
        // Run the following only if we have more than a thousand posts
        if ( $count > 1000 ) {
        
            // Get all post id after the first 1000 posts
            $set_to_trash = array_slice( $total_posts, 1000 );
            foreach ( $set_to_trash as $trash_post ) {
                // Use wp_trash_post to trash the posts 
                wp_trash_post( $trash_post  );
               // You can also use wp_delete_post here to delete everything attached to the post
               //wp_delete_post( $trash_post );
            }
            // Unset $trash_post for safety
            unset( $trash_post );
            
        }
        
    }
    
}, 10, 3 );

TO CONCLUDE

You can set your installation to permanently delete trashed posts by adding the following line to wp-config.php

define('EMPTY_TRASH_DAYS', 0 );

Just note, this will permanently delete posts and they cannot be recovered

Leave a Comment