Overcome the WordPress Autosave Limitations

WordPress includes a handy feature called ‘autosave’ that periodically persists an autosave version of a post at the moment of writing. Since accidents happen, it’s always good to have some recent version of a long text instead of starting from scratch when you don’t have the proper backup.

Autosave is handy, but since WordPress is no longer ‘yet another blogging platform’, it lacks important extensions to that feature.

When you work with custom post types (or even plain old posts and pages), you might need to alter the standard save behavior. Therefore you take advantage of the save_post hook. Then we could inject our own logic while saving the post and manage our own custom fields, logging, backup logic or whatsoever. Since the function would be called from autosaves, there is an extra conditional you need to take care of in the save_post callback to avoid duplications:


if( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {

return;

}

There are other use cases when you might need to take advantage of the full autosave API. For instance, displaying a live preview of your custom post type’s autosave version. Almost 2 years ago nacin had given a valid explanation of the idea of that feature, and in all it’s validity we’re pretty much stuck with that limitations.

I had a similar problem that led to taking some extra steps to overcome this limitation. Sure, it would have been great if JS filters were available in the core or the autosave API supported custom post fields, but that’s what we had there.

First off, in the metabox definition for the CPT, for all the custom fields in my metabox, I call a custom JS function of mine:


$('#widget-meta-wrapper section input, #widget-meta-wrapper section select').on('change', function() {
widget_autosave();
});

That function is defined in another JS file available on that page with a similar structure:


widget_autosave = function() {

var post_id = jQuery("#post_ID").val();

var post_data = {
'post_id': post_id,
'action': 'autosave_widget',
'width': jQuery('#widget-meta-wrapper input#width').val()
};

jQuery.ajax({
data: post_data,
type: "POST",
url: ajaxurl,
success: function( response ) {
// do some super handy stuff here
}
});
}

What’s important here is that we have an access to the post ID in the DOM tree and we could grab it easily, as well as other DOM elements from our metaboxes (if we set their IDs properly). We could iterate any kind of data that is available with JS and pass that with jQuery.

I’m also calling the AJAX POST with widget_autosave method. This is something that we need to handle separately. We’ll process that request with the admin-ajax functionality by defining an AJAX request handler the WordPress way:


add_action( 'wp_ajax_autosave_widget', array( $this, 'autosave_save_cpt' ) );

In our object function autosave_save_cpt we need to fetch the postdata from the widget_autosave function and update it:


public function autosave_save_cpt( ) {
if( ! empty ($_POST['post_id'] ) ) {
$post_id = $_POST['post_id'];
$width = ! empty( $_POST['width'] ) ? $_POST['width'] : 0;

if( ! empty( $width ) ) {
update_post_meta( $post_id, 'width', $width );
}
}

die();
}

That’s just a sample demo for the management – you have the access to the entire $_POST array filled from the widget JS handler so you can manage it in any possible way. The great thing here is that you could hook and use your own autosave. In addition to that, if you want your save to be attached to the same hook where the regular one is, you could do something like that in the constructor:


add_action( 'wp_ajax_autosave', array( $this, 'autosave_update_dialog' ), 1 );

And maintain some data persistence or even calling a standard save event for some reason (not that it won’t happen if you’ve save_post callback’d it):


public function autosave_update_dialog( ) {
$id = isset( $_POST['post_ID'] ) ? (int) $_POST['post_ID'] : 0;
if ( ! $id )
wp_die( -1 );

$this->meta_box_save( $id );
}

One thought on “Overcome the WordPress Autosave Limitations

  1. Someone please give this man a cookie! Finally, after searching for weeks, I’ve finally found a concrete answer to autosave custom metaboxes data. You just saved my night. Thank you very much.

Your thoughts?