WordPress.org

Make WordPress Core

Opened 6 years ago

Closed 3 years ago

Last modified 3 years ago

#9843 closed enhancement (fixed)

Duplicate autosave/revisions clutter the database

Reported by: Denis-de-Bernardy Owned by: westi
Milestone: 3.6 Priority: low
Severity: minor Version: 2.8
Component: Revisions Keywords: has-patch
Focuses: Cc:

Description

We shouldn't be storing revisions and autosaves that are identical to the original post.

It generates a bug, to start with. If you open a post, and you leave it alone until the autosave fires, and then close the window, you end up with a notice -- a newer version of the post exists.

Then, it clutters the list of actual revisions with junk that cannot be removed without a plugin or by using SQL.

Attachments (2)

tests_1213.patch (720 bytes) - added by soulseekah 3 years ago.
tests_1213.2.patch (761 bytes) - added by soulseekah 3 years ago.
alternative

Download all attachments as: .zip

Change History (22)

comment:1 @Denis-de-Bernardy6 years ago

  • Keywords needs-patch added
  • Milestone changed from 2.8 to Future Release
  • Priority changed from normal to low
  • Type changed from defect (bug) to enhancement

Mm, actually, the autosave issue described above seems fixed in trunk. But we're still cluttering the database with useless revisions. It's minor, too, so punting pending patch.

comment:2 @Denis-de-Bernardy6 years ago

I've this function on the save_post hook, in case there is any interest for a patch writer:

	function save_post_revision($rev_id) {
		if ( wp_is_post_autosave($rev_id) ) {
			return;
		} elseif ( $post_id = wp_is_post_revision($rev_id) ) {
			# do nothing
		} else {
			$post_id = $rev_id;
		}
		
		global $wpdb;
		$post = get_post($rev_id);
		
		# drop dup revs
		$kill_ids = $wpdb->get_col("
			SELECT	ID
			FROM	$wpdb->posts
			WHERE	post_type = 'revision'
			AND		ID <> " . intval($rev_id) . "
			AND		post_parent = " . intval($post_id) . "
			AND		post_content = '" . $wpdb->escape($post->post_content) . "'
			");
		
		if ( $kill_ids ) {
			foreach ( $kill_ids as $kill_id ) {
				wp_delete_post_revision($kill_id);
			}
		}
		
		# stop here for real posts
		if ( $post_id == $rev_id )
			return;
		
		# drop other potential dup revs
		$kill_ids = $wpdb->get_col("
			SELECT	p2.ID
			FROM	$wpdb->posts as p2
			JOIN	$wpdb->posts as p1
			ON		p1.post_parent = p2.post_parent
			AND		p1.post_type = p2.post_type
			WHERE	p1.post_type = 'revision'
			AND		p1.post_parent = " . intval($post_id) . "
			AND		p1.post_content = p2.post_content
			AND		p1.ID > p2.ID
			");

		if ( $kill_ids ) {
			foreach ( $kill_ids as $kill_id ) {
				wp_delete_post_revision($kill_id);
			}
		}
		
		# drop near-empty revs
		$kill_ids = $wpdb->get_col("
			SELECT	ID
			FROM	$wpdb->posts
			WHERE	post_type = 'revision'
			AND		post_parent = " . intval($post_id) . "
			AND		LENGTH(post_content) <= 50
			");
		
		if ( $kill_ids ) {
			foreach ( $kill_ids as $kill_id ) {
				wp_delete_post_revision($kill_id);
			}
		}
		
		# drop adjascent revs
		$kill_ids = $wpdb->get_col("
			SELECT	p2.ID
			FROM	$wpdb->posts as p2
			JOIN	$wpdb->posts as p1
			ON		p1.post_parent = p2.post_parent
			AND		p1.post_type = p2.post_type
			WHERE	p1.post_type = 'revision'
			AND		p1.post_parent = " . intval($post_id) . "
			AND		DATEDIFF(p1.post_date, p2.post_date) < 1
			AND		p1.post_date >= p2.post_date
			AND		p1.ID <> p2.ID
			");

		if ( $kill_ids ) {
			foreach ( $kill_ids as $kill_id ) {
				wp_delete_post_revision($kill_id);
			}
		}
		
		# drop near-identical revs
		$kill_ids = $wpdb->get_col("
			SELECT	p2.ID
			FROM	$wpdb->posts as p2
			JOIN	$wpdb->posts as p1
			ON		p1.post_parent = p2.post_parent
			AND		p1.post_type = p2.post_type
			WHERE	p1.post_type = 'revision'
			AND		p1.post_parent = " . intval($post_id) . "
			AND		DATEDIFF(p1.post_date, p2.post_date) <= 7
			AND		ABS( LENGTH(p1.post_content) - LENGTH(p2.post_content) ) <= 50
			AND		p1.post_date >= p2.post_date
			AND		p1.ID <> p2.ID
			");

		if ( $kill_ids ) {
			foreach ( $kill_ids as $kill_id ) {
				wp_delete_post_revision($kill_id);
			}
		}
	} # save_post_revision()

comment:3 @caesarsgrunt6 years ago

Duplicate of #7392.

comment:4 @Denis-de-Bernardy6 years ago

similar, but not 100% dup. #7392 only covers autosaves. here, it's more like: don't create a revision if only a post's tags have been edited.

comment:6 @AmbushCommander5 years ago

  • Cc AmbushCommander added

comment:7 @scribu5 years ago

  • Cc scribu@… added

comment:8 @solarissmoke5 years ago

I've posted a patch on #7392 which I think should resolve both of these.

comment:9 @westi3 years ago

  • Keywords revisions-3.6 added

Adding to the list of things to consider for the 3.6 work on Revisions.

comment:10 @westi3 years ago

  • Keywords revisions-3.6 removed
  • Milestone changed from Future Release to 3.6

This need careful consideration and we will take a look for 3.6.

comment:11 @adamsilverstein3 years ago

i think solving #7392 will solve this issue; the initial autosave firing is what creates the extra revision record mentioned by the author in this post. by the way, if you create a post, but go immediately to publish button from the title field without entering any content the extra revision is not created.

comment:12 @adamsilverstein3 years ago

  • Keywords has-patch added; needs-patch removed

verified, #7392 patch fixes this.

comment:13 @ethitter3 years ago

  • Cc erick@… added

comment:14 @adamsilverstein3 years ago

  • Cc adamsilverstein@… added

comment:15 @westi3 years ago

In 1211/tests:

Revisions: When we are trying to save a new revision we shouldn't save one if the previous version was the same.

See #7392 and #9843 props adamsilverstein

comment:16 @westi3 years ago

  • Owner set to westi
  • Resolution set to fixed
  • Status changed from new to closed

In 23414:

Revisions: Before saving a new post revision make sure that something has changed in the fields that we are revisioning.

Fixes: #7392 and #9843 props adamsilverstein.

comment:17 @westi3 years ago

In 1214/tests:

Revisions: Add a new test for a force save filter in wp_save_post_revision

Also Update the tests to have correct ordering, be less complex and use things like assertCount.
See #7392 and #9843

comment:18 @westi3 years ago

In 23415:

Revisions: Allow a plugin to force us to skip the don't save this revision because it hasn't changed code if it knows better.

See #7392 and #9843. Also cleans up the whitespace.

comment:19 @soulseekah3 years ago

Breaks post/revisions/test_revision_restore_caps_before_publish, since content hasn't changed a revision was not created, expected 2 revisions after second "edit", getting one.

Test was written for #16847 http://core.trac.wordpress.org/changeset/1213/tests and should probably change content the second time to create a second revision, or expect 1 revision.

Last edited 3 years ago by soulseekah (previous) (diff)

@soulseekah3 years ago

@soulseekah3 years ago

alternative

comment:20 @kovshenin3 years ago

  • Cc kovshenin added
Note: See TracTickets for help on using tickets.