Delete post revisions on post publish

Is it possible to delete post/page revisions from the database when a post/page is published?

11/05/12 Answer: See the plugin below by bueltge

Read More

I want to do this on a site with 5,000 posts and 125,000 comments; it’s on a VPS and can handle the wp_posts table size – before I deleted all revisions, the table was 1.5 gigs – but I still want to keep the overall database size to a minimum by preventing revisions.

But, the client tells me he lost a big post due to a browser freeze, so: is it possible to delete post/page revisions from the database for each post/page when it is published?

What hook would be used? Is save_post the correct one? http://codex.wordpress.org/Plugin_API/Action_Reference/save_post

I have the autosave parameter set in wp-config.php, but according to the docs, that autosaves the post/page as it is being worked on, and overwrites each autosave.

What I want to do is have revisions accumulate for drafts – however many, depending on how many times “Save” and “Update” are used by the author – but once the draft is published, delete all revisions. There will only be revisions for the one post, but rather than try and parse the post_ID, the SQL query can run through all posts.

This is what I’m trying in functions.php, but I get a Call to a member function query() on a non-object error.

function delete_revisions_on_publish( $post_id ) {

    if ( !wp_is_post_revision( $post_id ) ) {

remove_action('save_post', 'delete_revisions_on_publish');

    $wpdb->query( 
    $wpdb->prepare( 
    "DELETE a,b,c
    FROM wp_posts a
    LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id)
    LEFT JOIN wp_postmeta c ON (a.ID = c.post_id)
    WHERE a.post_type = 'revision' "
        )
);
        }
}
add_action( 'save_post', 'delete_revisions_on_publish' );

Related posts

Leave a Reply

3 comments

  1. I think a small plugin with the hook ‘publish_posts’ is enough. But I dont know about a core function to delete revisions and I use a query with WP functions. The source is untested, written only for this post.

    <?php
    /**
     * Plugin Name: WPSE71248 Delete Revisions on Publish Posts
     * Plugin URI:  http://wordpress.stackexchange.com/questions/71248/
     * Description: 
     * Version:     1.0.0
     * Author:      Frank Bültge
     * Author URI:  http://bueltge.de
     * License:     GPLv3
     */
    
    ! defined( 'ABSPATH' ) and exit;
    
    add_action( 'publish_post', 'fb_remove_revisions' );
    
    function fb_remove_revisions( $post_id = FALSE ) {
    
        $post_id = (int) $post_id;
    
        $revisions = '';
        // Get the revisions
        $revisions = new WP_Query( array(
            'post_status'    => 'inherit',
            'post_type'      => 'revision',
            'showposts'      => -1,
            'posts_per_page' => -1,
            'post_parent'    => $post_id
        ) );
    
        if ( empty( $revisions ) )
            return $post_id;
    
        // Remove the revisions the non-core-way
        global $wpdb;
        foreach ( $revisions->posts as $revision ) {
            $query = $wpdb->prepare(
                "
                DELETE FROM $wpdb->posts 
                WHERE ID = %d
                AND post_parent = %d
                ",
                $revision->ID, 
                $post_id
            );
            $wpdb->query( $query );
        }
    
        return $post_id;
    }
    

    Alternative use the download from Gist 4017151

  2. I would prefer a different approach to achieve that. Rather than using the global $wpdb to directly access DB and delete revisions, I have used WP functions. The following code will delete revisions on Publish or Update of all post types that supports revisions and have a publish status:

    add_action( 'admin_init', 'add_delete_revision_actions' );
    function add_delete_revision_actions () {
    
        // get all post types, except 'revision'
        $post_types = get_post_types( array( 'exclude_from_search' => false ) );
    
        // add action for each post type that supports 'revisions'
        foreach ($post_types as $post_type) {
            if ( post_type_supports( $post_type, 'revisions' )) {
                add_action("publish_$post_type", 'delete_revisions_on_publish', 10, 1);
            }
        }
    }
    
    function delete_revisions_on_publish ($post_id) {
    
        // get revisions for this post
        $revisions = wp_get_post_revisions($post_id);
    
        // .. and delete it
        foreach ($revisions as $revision) {
            $delete = wp_delete_post_revision($revision->ID);
            // check for errors
            // if ( is_wp_error($delete) ) { ... }
        }
    }
    
  3. It should be possible and it looks like you are on the right track.

    To solve your “Call to a member function” error, I believe you need global $wpdb; at the top of that function.

    I think the hook formerly know as publish_post would be a better hook for you as it is specific to published posts. save_post will run for all saves.

    Also, you say that “the SQL query can run through all posts” but that will erase revisions for all drafts if you have more than one post in the works, or if you save an edit to a published post while you have a draft in the works. Anyway, that is your choice, but you don’t need $wpdb->prepare at all if you do that. There is no input other than the hard coded SQL string so there is no need to ‘prepare’ anything.

    $wpdb->query( 
        $wpdb->prepare( 
        "DELETE a,b,c
        FROM wp_posts a
        LEFT JOIN wp_term_relationships b ON (a.ID = b.object_id)
        LEFT JOIN wp_postmeta c ON (a.ID = c.post_id)
        WHERE a.post_type = 'revision' 
        AND a.ID = %d",
        $post_id
      )
    );