Revisions: Add a way to filter the revisions considered for deletion.

This changeset introduces a new filter for `wp_save_post_revision()`. `wp_save_post_revision_revisions_before_deletion` passes the revisions to be considered for deletion, and the new revision's post ID.

This allows extenders to exclude specific revisions from being considered for deletion.

Props jhned, costdev, audrasjb, adamsilverstein, mukesh27.
Fixes #57320.


git-svn-id: https://develop.svn.wordpress.org/trunk@55254 602fd350-edb4-49c9-b593-d223f7449a82
This commit is contained in:
Jb Audras
2023-02-07 12:38:01 +00:00
parent 3a9555ab84
commit 6636a6979f
2 changed files with 140 additions and 0 deletions

View File

@@ -200,6 +200,35 @@ function wp_save_post_revision( $post_id ) {
$revisions = wp_get_post_revisions( $post_id, array( 'order' => 'ASC' ) );
/**
* Filters the revisions to be considered for deletion.
*
* @since 6.2.0
*
* @param WP_Post[]|int[] $revisions Array of revision objects or IDs,
* or an empty array if none.
* @param int $post_id The ID of the post to save as a revision.
*/
$filtered_revisions = apply_filters(
'wp_save_post_revision_revisions_before_deletion',
$revisions,
$post_id
);
if ( is_array( $filtered_revisions ) ) {
$revisions = $filtered_revisions;
} else {
_doing_it_wrong(
__FUNCTION__,
sprintf(
/* translators: %s: The filter name. */
__( 'The "%s" filter should return an array.' ),
'wp_save_post_revision_revisions_before_deletion'
),
'6.2.0'
);
}
$delete = count( $revisions ) - $revisions_to_keep;
if ( $delete < 1 ) {

View File

@@ -866,4 +866,115 @@ class Tests_Post_Revisions extends WP_UnitTestCase {
add_post_type_support( 'post', 'revisions' );
}
/**
* Tests that wp_save_post_revision() respects the 'wp_save_post_revision_revisions_before_deletion' filter
* when deleting revisions.
*
* This test should protect the original revision, send the rest to be checked against wp_revisions_to_keep(),
* and result in two revisions: The latest revision, and the original.
*
* @ticket 57320
*
* @covers ::wp_save_post_revision
*/
public function test_wp_save_post_revision_should_respect_revisions_before_deletion_filter() {
$post_id = self::factory()->post->create( array( 'post_title' => 'Test 57320' ) );
add_filter(
'wp_revisions_to_keep',
static function() {
return 1;
}
);
add_filter(
'wp_save_post_revision_revisions_before_deletion',
static function ( $revisions ) {
// Ignore the first revision and return the rest for deletion.
return array_slice( $revisions, 1 );
}
);
for ( $update = 1; $update < 4; ++$update ) {
wp_update_post(
array(
'ID' => $post_id,
'post_title' => 'Test 57320 Update ' . $update,
)
);
}
$actual = wp_get_post_revisions( $post_id );
$this->assertCount(
2,
$actual,
'There should be two revisions.'
);
$first = reset( $actual );
$second = next( $actual );
$this->assertSame(
'Test 57320 Update 3',
$first->post_title,
'The title of the first revision was incorrect.'
);
$this->assertSame(
'Test 57320 Update 1',
$second->post_title,
'The title of the second revision was incorrect.'
);
}
/**
* Tests that wp_save_post_revision() ignores an invalid return value
* from the 'wp_save_post_revision_revisions_before_deletion' filter
* and throws _doing_it_wrong().
*
* @ticket 57320
*
* @covers ::wp_save_post_revision
*
* @expectedIncorrectUsage wp_save_post_revision
*/
public function test_wp_save_post_revision_should_ignore_invalid_revisions_before_deletion_filter() {
$post_id = self::factory()->post->create( array( 'post_title' => 'Test 57320' ) );
add_filter(
'wp_revisions_to_keep',
static function() {
return 1;
}
);
add_filter( 'wp_save_post_revision_revisions_before_deletion', '__return_null' );
for ( $update = 1; $update < 4; ++$update ) {
wp_update_post(
array(
'ID' => $post_id,
'post_title' => 'Test 57320 Update ' . $update,
)
);
}
$actual = wp_get_post_revisions( $post_id );
$this->assertCount(
1,
$actual,
'There should only be one revision.'
);
$first = reset( $actual );
$this->assertSame(
'Test 57320 Update 3',
$first->post_title,
'The title of the first revision was incorrect.'
);
}
}