WordPress Tip: Careful with that Autosave, Eugene

After upgrading WordPress from version 2.0.5 to 2.3.3, I did some experimenting with the “post autosave” feature. The autosave feature uses some crafty ajax to automagically save your post every 2 minutes (120 seconds by default). Below the post-editing field, you will notice a line of text that displays the time of the most recent autosave, similar to the following:

[ Screenshot: WordPress Autosave Message (Saved at 2:34:02.) ]

Surely, this relatively new feature provides an added layer of protection against lost work, but all is not perfect (yet) in the world of automatically saved content.

Several months ago, I lost several hours of work because the autosave feature completely failed to work, despite the periodically reassuring “Saved at..” message. After working for several hours with a false sense of security, WordPress choked and my post had vanished. In shock, I scoured the database for any trace of my recent efforts, but to no avail. The entire post had disappeared into the void. Utterly devastated and disillusioned, I decided to investigate the so-called “autosave” feature, learn what had happened, and take steps to avoid such travesty in the future. Here is a summary of my investigation..

A few notes on the WordPress Autosave feature

The reason autosave failed — Although autosave seemed to be working as expected, all data was lost after I had clicked the “Save” button and received an unexpected server error. Apparently, either my server or WordPress (or both?) doesn’t respond well to various types of character combinations (e.g., the term “.htaccess”), and will utterly reject any post input containing such “invalid” content.

So, without realizing that I had included some forbidden character string, I habitually hit the save button, only to trigger an error and get redirected to a server-error page. Oops, but not a big deal, right? After all, “WordPress Autosave has my back.” Or so I thought. Upon returning to the admin screen, I found no trace of my post. A thorough examination of the database confirmed that autosave had saved absolutely nothing: I lost three-plus hours of diligent work — poof! — just like that.

Moral of the drama: Don’t rely on WordPress Autosave if the possibility exists that your content will trigger an error when saving or publishing your post. I can’t say that autosave will always fail in such cases, but I can say that it is definitely possible. Moving on..

How do you know if autosave actually worked? — If autosave managed to do its job and save your post content, WordPress will display a link to a draft of your saved post. I have seen this link in either of two places, depending on your user status:

  • as an individual link located above the post-editing panel, or
  • mixed in with other posts listed within the post management panel

If you think that you may have lost some content, and don’t see a draft version of your autosaved post in either of these locations, an autosave failure is highly probable. You may have better luck than I did, however, by searching through your associated WordPress database for the missing content. If you did lose work, believe me, I feel your pain.

Implement a backup strategy — As nice as the concept of “autosave” sounds, don’t rely on it to save your work. Think of it as an added layer of protection against boo-boos, but treat it as nothing more than a bonus feature that may or may not work as intended. Seriously, losing three hours of meticulously crafted material is a total drag. Since then, I have adopted a new strategy for backing up my posts while working on them:

  1. Work for few minutes or type a few paragraphs
  2. Ctrl-A, Ctrl-C, Ctrl-V into a blank .txt file
  3. Work for few minutes or type a few paragraphs
  4. Ctrl-A, Ctrl-C, Ctrl-V to replace previous .txt copy
  5. Wash, rinse, repeat..

I have been doing this for several months now, and the practice has become almost second-nature. It takes only a few extra keystrokes and a few microseconds, but the habit has already saved my rear on several occasions. Then, as an added bonus, when I am finished writing the post, I also copy & paste the date, title, keywords, description, excerpt, and tags to the text file, save it as the name and date, and zip the monthly collection of posts into a nice archive directory. Paranoid and tedious? Perhaps. Time-saving and reassuring? Definitely.

How to change the time-interval for the WordPress Autosave feature

While experimenting with the autosave feature for this post, I discovered how easy it is to change the default autosave time interval. In WordPress 2.3 (and probably 2.2 and 2.1), open the wp-includes/script-loader.php and edit the instance of 120 (seconds) to something more appropriate. Don’t get too crazy though, or you might get a nasty email from your host. Here is how the interval-setting code appears on line #43:

'autosaveInterval' => apply_filters('autosave_interval', '120'),

Other stupid Autosave tricks..

While tinkering, I also learned that it is just as easy to customize the default messages displayed throughout the autosave process. While saving your draft, WordPress displays the text, “Saving Draft…”. Then, in between saves, the text “Saved at 2:34:02”, as displayed in the previous screenshot. To change either of these default messages, open the same file as before (wp-includes/script-loader.php), and edit the following lines to suit your needs:

// line #45 >>
'saveText' => __('Saved at %time%.'),

// line #47 >>
'savingText' => __('Saving Draft...')

Other interesting autosave quirks

Also during the investigation, I happened to stumble upon an interesting discovery concerning a common technique for displaying a blog’s annual archives. WordPress provides the following built-in methods of querying and displaying daily and monthly archive listings:

<?php wp_get_archives('type=postbypost'); ?>

<?php wp_get_archives('type=monthly&show_post_count=1'); ?>

However, earlier versions of WordPress did not provide similar functionality for the presentation of yearly archives. To accommodate this missing feature, many WordPress users and theme developers have employed the following, highly prevalent method:

<ul id="archives">
	<?php $years = $wpdb->get_col("SELECT DISTINCT YEAR(post_date) FROM $wpdb->posts ORDER BY post_date DESC"); foreach($years as $year) : ?>
		<li><a href="<?php echo get_year_link($year); ?>"><?php echo $year; ?></a></li>
	<?php endforeach; ?>
</ul>

Fair enough, that trick definitely does the job, however, drafts and autosaved posts produce some unexpected results. Specifically, post drafts are stored along with published posts in the wp_posts database table. Thus, the above query returns a “year” for all post drafts and displays their values in the annual archive list. Any post draft that happens to be a working “autosave” draft will return a zero (i.e., “0”) for the above yearly archive query (see screenshot). In other words, drafts are saved with a post_date of zero. Also, any posts that are deliberately saved as “draft” (i.e, any post that is not published) will also display a zero if the previous database query is used. Fortunately, there are at least THREE easy ways to prevent meaningless zeros from populating your annual archive list:

1. Re-save the draft(s) with an explicit time stamp (hint: pick a year that already exists in the annual archives).
2. For users of WP versions less than 2.3, tweak the database query to ignore posts with “draft” status:

<ul id="archives">
	<?php $years = $wpdb->get_col("SELECT DISTINCT YEAR(post_date) FROM $wpdb->posts WHERE post_status = 'publish' ORDER BY post_date DESC"); foreach($years as $year) : ?>
		<li><a href="<?php echo get_year_link($year); ?> "><?php echo $year; ?></a></li>
	<?php endforeach; ?>
</ul>

3. Even better, for WordPress 2.3 and beyond, simply replace the direct database call with the new “built-in” hotness:

<ul>
	<?php wp_get_archives('type=yearly&show_post_count=1'); ?>
</ul>

This third method includes several useful parameters, including the ability to display the post count next to each year.

Wrap up..

That’s it for this post! See you next time with another fun-filled and educational adventure into WordPress land!