Take the 2-minute tour ×
WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. It's 100% free, no registration required.

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

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' );
share|improve this question
add comment

3 Answers 3

up vote 4 down vote accepted

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

share|improve this answer
    
Looks good and it should work, but I get a parse error on the public function fb_remove_revisions( $post_id = FALSE ) { line. –  songdogtech Nov 4 '12 at 2:12
    
Remove the 'public', it is from use in class. I will update the answer. –  bueltge Nov 4 '12 at 22:25
    
Thanks! That doesn't crash now, but it doesn't delete revisions. Is there some sort of query log I can enable to see what its doing/not doing? –  songdogtech Nov 4 '12 at 22:49
    
The delete sql was the problem, a string was empty. Now I have tested and it works. I have also created a plugin, easy to use after activation. –  bueltge Nov 5 '12 at 13:19
    
Thanks! I was going to suggest a plugin. Works great; tested on my localhost and live site. (Edited a few typos in your answer). –  songdogtech Nov 6 '12 at 1:21
show 1 more comment

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
  )
);
share|improve this answer
1  
Thanks! I'm kind of a beginner at php. How would I implement {$new_status}_{$post->post_type}? And that's a good point about all other drafts; I need to just delete the revisions for the one post; so I need to pass the post_iD to the function? –  songdogtech Nov 2 '12 at 13:03
    
In your case {$new_status}_{$post->post_type} would be publish_post -- status + post type. Yes, you should pass the post_ID in order to limit the query to only that post. I'll edit my answer to add that. –  s_ha_dum Nov 2 '12 at 14:03
    
s_ha_dum, thanks for the suggestion; check out bueltge's plugin above. –  songdogtech Nov 6 '12 at 12:58
    
@songdogtech seems you are expert rather than beginer of php:) –  hugemeow Nov 14 '12 at 13:00
add comment

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) ) { ... }
    }
}
share|improve this answer
    
This actually deletes all revisions on any post edit or publish. –  songdogtech Nov 4 '12 at 2:14
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.