Make WordPress Core

Opened 16 years ago

Closed 16 years ago

Last modified 15 years ago

#6775 closed enhancement (fixed)

Post Revisions

Reported by: mdawaffe's profile mdawaffe Owned by: mdawaffe's profile mdawaffe
Milestone: 2.6 Priority: normal
Severity: normal Version: 2.5.1
Component: General Keywords: revision needs-testing has-patch blessed
Focuses: Cc:

Description

Overview

Attached is a first pass at adding basic versioning/revisioning to WordPress.

What it does:

  1. Saves a copy of a post every time you edit it.
  2. Allows you to view (not edit) each of those copies (revisions).
  3. Shows diffs between any two revisions. Forward (in time) diffs only.

What it doesn't do:

  1. You cannot have a live-revision and a working revision to be pushed live later. I'm not sure if that feature would be useful to our core audience or not. At any rate, it's a little tricky to get working correctly.

How it works

Posts are copied into a new row in the posts table on the pre_post_update hook. Only certain (configurable by plugin) fields are saved (title, content, author, excerpt). The rest are either used internally by WP somewhere or I felt weren't useful to save.

Posts can be restored from an older revision either in full or field by field (not chunk by chunk).

The Diff engine is an extension of the PEAR Text_Diff package (which I believe to be the descendent of the MediaWiki Diff engine). The generation of the diff output is fully pluggable via the new wp_text_diff() pluggable function.

The provided function shows diffs "side by side" and with both line and word highlighting (trac style). The old content is on the left, and the new content is on the right. This presentation allows you to ignore all the color highlighting and plusses and minuses and just read either side from top to bottom to see what the post looked like in that revision.

Functions provided:

  • wp_text_diff( $left_string, $right_string, $args = null )
  • wp_save_revision( $post_id )
  • wp_get_revision(&$post, $output = OBJECT, $filter = 'raw')
  • wp_restore_revision( $revision_id, $fields = null )
  • wp_delete_revision( $revision_id )
  • wp_get_post_revisions( $post_id = 0 )
  • wp_list_post_revisions( $post_id = 0, $args = null )

TODO

  1. Open up revisions for pages as well. That's where they'll be most useful.
  2. Rework Autosave to store its data as a special post revision. Then we'll be able to autosave *all* posts/pages (not just drafts) and have recovery messages like "WordPress found an autosaved copy of this post that's more recent than your version, would you like to see it?"
  3. Review caps/permissions. Do we need any new ones like current_user_can( 'view_revision', $id )?
  4. Display revisions and/or diffs in front end?
  5. Decide how many revisions to store for each post. Right now it stores an arbitrary number. Should it be capped?

Prior work and idea sources

  1. http://wordpress.org/extend/plugins/post-revisions/ (me)
  2. http://wordpress.org/extend/plugins/blicki/ (Ryan)
  3. http://comox.textdrive.com/pipermail/wp-hackers/2008-March/018689.html (Paul Menard)

Committer:

svn add wp-includes/Text
svn add wp-incledes/wp-diff.php
svn add wp-admin/revision.php

Attachments (8)

6775.diff (91.2 KB) - added by mdawaffe 16 years ago.
6775.2.diff (34.4 KB) - added by mdawaffe 16 years ago.
Autosave
6775.3.diff (5.0 KB) - added by mdawaffe 16 years ago.
Pages
6775.4.diff (1.9 KB) - added by mdawaffe 16 years ago.
cap tweaks (independent of 6775.3.diff)
6775.5.diff (2.3 KB) - added by mdawaffe 16 years ago.
delete deleted post's revisions, constant for turning off revisions
6775.6.diff (2.0 KB) - added by mdawaffe 16 years ago.
6775.7.diff (20.1 KB) - added by mdawaffe 16 years ago.
6775.8.diff (3.2 KB) - added by mdawaffe 16 years ago.
validation

Download all attachments as: .zip

Change History (52)

@mdawaffe
16 years ago

#1 @mdawaffe
16 years ago

Right now, because of autosave, the attached will save a "blank" revision. Just ignore it, we'll work out the kinks when we port autosave.

#2 @mdawaffe
16 years ago

More TODO:

  1. See if get_last*modified() need any adjusting.

#3 @ryan
16 years ago

(In [7747]) Post revisions from mdawaffe. see #6775

#4 @Viper007Bond
16 years ago

Wow, that's one big patch!

Nitpick: why is "Text" capitalized?

#5 follow-ups: @DD32
16 years ago

Nitpick: why is "Text" capitalized?

Because thats the naming proceedure which the package uses, (Which looks to be Horde)

require_once 'Text/Diff/Renderer.php';

Is that going to be an issue on systems which do not have the wp-includes directory in the include search path?

#6 in reply to: ↑ 5 @Viper007Bond
16 years ago

Replying to DD32:

Because thats the naming proceedure which the package uses,

Gotcha.

#7 in reply to: ↑ 5 @mdawaffe
16 years ago

require_once 'Text/Diff/Renderer.php';

Is that going to be an issue on systems which do not have the wp-includes directory in the include search path?

There's an ini_set() in wp_text_diff(): http://trac.wordpress.org/browser/trunk/wp-includes/pluggable.php?rev=7747#L1377 and later an ini_restore().

I don't know if that will work on all systems, but I wanted to try it first rather than modifying the code. (Though I've already modified it in the sense that I've left out about half of the package.)

#8 in reply to: ↑ description @Dickie
16 years ago

Replying to mdawaffe:

Overview

What it doesn't do:

  1. You cannot have a live-revision and a working revision to be pushed live later. I'm not sure if that feature would be useful to our core audience or not. At any rate, it's a little tricky to get working correctly.

That's a real shame, as that is something that I personally would find really handy, as I generally use WP as a CMS not a blog and to be able to make modifications to a post without actually committing them yet would be great... (The history side of things is useful but less important to me).
I would also like to be able to change multiple pages all at once, and then commit them all with one deft stroke of the mouse ;)
But that's just my £0.02

#9 follow-up: @neoen
16 years ago

Will be possible to turn off post revisions and use only current autosave?

#10 @matt
16 years ago

  • Keywords blessed added

#11 @markjaquith
16 years ago

(In [7817]) Fix typo in wp_save_revision(). props Andy. see #6775

#12 in reply to: ↑ 9 @mdawaffe
16 years ago

Replying to neoen:

Will be possible to turn off post revisions and use only current autosave?

No - Autosave will use the new revisions system. There may be a (hidden) option to limit how many revisions WP should keep for any given post. If we do that, then setting it to 0 would mean "do autosaves, but don't keep post revisions".

#13 @mdawaffe
16 years ago

  • Owner changed from anonymous to mdawaffe
  • Status changed from new to assigned

6775.2.diff

  1. Moves autosave to post revisions. For drafts, autosave overwrites the post (this is the same as the old behavior). For non-drafts, a special post revision is inserted into the posts table.

Only one autosave is stored per post.

The philosophy here is that a new post revision is created every time the user clicks one of the save buttons, but not for each autosave.

  1. Turns on autosave for all posts.
  2. Displays warning when a user edits a post for which there is an autosave more recent than the post itself.
  3. Consolidates code from edit_post() and wp_write_post().
  4. Refactors wp-admin/revision.php into switch( $action ) : like our other "object" pages.

Still TODO:

  1. Open up revisions for pages as well. It's mostly there, but probably needs some tweaks. Pages might be a bit broken right now, in fact.
  2. Review caps/permissions. Do we need any new ones like current_user_can( 'view_revision', $id )?
  3. Display revisions and/or diffs in front end?
  4. Decide how many revisions to store for each post. Right now it stores an arbitrary number. Should it be capped?
  5. See if get_last*modified() need any adjusting.

New functions:

wp_get_autosave( $post_id );
wp_create_autosave();
_wp_translate_postdata(); // Rename $_POST data from form names to DB post columns

@mdawaffe
16 years ago

Autosave

#14 @ryan
16 years ago

Viewing diff results in infinite redirect. $redirect is "/trunk/wp-admin/revision.php?action=diff&right=59&left=58" every time.

#15 @ryan
16 years ago

Found it. Small typo in the code that checks for reversed diffs.

#16 @ryan
16 years ago

(In [7907]) Move autosave to post revisions. Props mdawaffe. see #6775

#17 @mdawaffe
16 years ago

6775.3.diff

  1. Turn on revisions for pages.

@mdawaffe
16 years ago

Pages

#18 @mdawaffe
16 years ago

Ryan feels that current caps for edit_post, read_post, etc are all fine to use with revisions as well. I'll look over the cap code to see if we should check caps against the post_parent if 'inherit' == post_status.

#19 @mdawaffe
16 years ago

get_last*modified() are fine.

#20 @mdawaffe
16 years ago

6775.4.diff (independent of .3.diff)

  1. Tweak some caps.

@mdawaffe
16 years ago

cap tweaks (independent of 6775.3.diff)

#21 @mdawaffe
16 years ago

  • Keywords has-patch added

6775.diff (independent of .3.diff and .4.diff)

  1. Delete post revisions of deleted post.
  2. Turn off post revisions with WP_POST_REVISIONS constant in wp-config.php or during plugins_loaded action.

#22 @mdawaffe
16 years ago

All the above backend TODOs are now done with patches .3.diff, .4.diff and .5.diff.

We need to decide if we want to be able to display revisions and/or diffs blog-side.

The admin-side UI needs a general going over.

UI for deleting revisions?

@mdawaffe
16 years ago

delete deleted post's revisions, constant for turning off revisions

#23 @ryan
16 years ago

(In [7913]) Revisioning for pages from mdawaffe. see #6775

#24 @ionfish
16 years ago

Using revisions seems to break the saving of tag associations. Currently looking into it.

#25 @ionfish
16 years ago

Seems to be fine on a fresh install. Probably just something screwy in my database.

#26 @Viper007Bond
16 years ago

I'm having issues with the revisions being attributed to the wrong user.

#27 @DD32
16 years ago

I'm having issues with the revisions being attributed to the wrong user.

I think that may be due to a bug in #6964, Could you give the changes from my patch on that ticket to wp-admin/edit-form-advanced.php a try?

#28 @Viper007Bond
16 years ago

Yeah, that fixes it.

#29 @mdawaffe
16 years ago

6775.6.diff

  1. Allow get_posts() args to be passed to wp_get_post_revisions().
  2. WP_POST_REVISIONS can be
    • true (default), -1: Save all revisions.
    • false, 0: Save no revisions. Only do autosave.
    • (int) > 0: Only save that # of revisions + 1 autosave. Older revisions are deleted.

@mdawaffe
16 years ago

#30 @ryan
16 years ago

(In [7987]) Allow defining the number of revisions to save. Props mdawaffe. see #6775

#31 @mdawaffe
16 years ago

I don't think core needs to have any bulit in functionality for displaying revisions/diffs on the front end. Themers/Pluginers can address that with rewrite endpoints, and the current revisions API.

#32 @mdawaffe
16 years ago

6775.7.diff

  1. Consistency in function names: rename from *_revision* to *_post_revision*.
  2. If WP_POST_REVISIONS is set to false, allow autosaves to be viewed, diffed, restored via revisions UI. Do not allow similar for other revisions.
  3. New convenience functions: wp_is_post_revision(), wp_is_post_autosave().

@mdawaffe
16 years ago

#33 @ryan
16 years ago

(In [8011]) Post revisions API cleanup from mdawaffe. see #6775

#34 @mdawaffe
16 years ago

6775.8.diff

Validation errors.

@mdawaffe
16 years ago

validation

#35 @ryan
16 years ago

(In [8012]) Validation fixes for post revisions. Props mdawaffe. see #6775

#36 follow-up: @johnhennmacc
16 years ago

Are there plans to allow a user to delete revisions through the administration screens? Another idea would be to delete revisions when a post gets published. It's very easy to build up revisions if you save every few minutes and that adds to the size of your database. Going in and doing deletions from database tables is all very fine but clearing up things through a UI is much more convenient. I am curious as your thoughts on this. Otherwise, I can see post revisions being very useful things to have.

#37 in reply to: ↑ 36 @Viper007Bond
16 years ago

Replying to johnhennmacc:

It's very easy to build up revisions if you save every few minutes and that adds to the size of your database.

Why are you saving every few minutes? Autosave does it for you every 60 seconds and only uses one post revision.

#38 @ryan
16 years ago

(In [8175]) don't show autosave message if post and autosave are 'identical'. Props mdawaffe. see #6775

#39 @ryan
16 years ago

(In [8176]) better handling of comparing a revision to itself. Props mdawaffe. see #6775

#40 @ryan
16 years ago

  • Resolution set to fixed
  • Status changed from assigned to closed

#41 follow-up: @rawalex
16 years ago

Can there be something added in settings to allow blog owners to decide if they want to save revisions or not? Not everyone needs this functionality or wants to increase the size of the data files to accommodate it.

#42 @rawalex
16 years ago

  • Resolution fixed deleted
  • Status changed from closed to reopened

#43 in reply to: ↑ 41 @westi
16 years ago

  • Resolution set to fixed
  • Status changed from reopened to closed

Replying to rawalex:

Can there be something added in settings to allow blog owners to decide if they want to save revisions or not? Not everyone needs this functionality or wants to increase the size of the data files to accommodate it.

Firstly please don't re-open enhancement tickets when the feature has been released.

Secondly, you can disable the post revision code with a define in your wp-config.php file by adding define('WP_POST_REVISIONS','0');.

#44 @Viper007Bond
16 years ago

westi types faster than me, but here's my reply anyway:

1) For future reference, please open your own ticket rather opening up a resolved ticket.

2) Such a feature already exists via the WP_POST_REVISIONS constant (see mdawaffe's above comment). Please try searching first next time too.

3) Like all user content, revisions are stored in your database, not files.

Note: See TracTickets for help on using tickets.