Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update revision meta storage format for consistency #56

Merged
merged 12 commits into from
Mar 13, 2020
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![Build Status](https://travis-ci.org/adamsilverstein/wp-post-meta-revisions.svg?branch=master)](https://travis-ci.org/adamsilverstein/wp-post-meta-revisions)

=== WP-Post-Meta-Revisions ===
* Contributors: adamsilverstein, mattheu
* Contributors: adamsilverstein, mattheu, aaemnnosttv
* Requires at least: 4.1
* Tested up to: 4.9
* Stable tag: 1.0.0
Expand All @@ -12,6 +12,9 @@ Allow selected post meta keys to be tracked in revisions.

== Description ==

## Important
**Version 2.0.0** of this plugin introduces a streamlined storage format for revisioned meta that is not completely backwards compatible with previous versions of the plugin. Restoring revisions data from a previous version where array data was stored may not work as expected. If you need to be able to restore array data revisioned in previous versions, avoid upgrading or read the full issue to see how your data may be impacted: https://github.com/adamsilverstein/wp-post-meta-revisions/pull/56/.

This plugin implements a <i>post meta revisioning</i> feature as arrived at in https://core.trac.wordpress.org/ticket/20564.

The goal of releasing this code as a plugin is to allow as many people as possible to easily test the post meta revisioning feature, and also hopefully move towards inclusion of the feature into core, following the <a href="https://make.wordpress.org/core/features-as-plugins/">Features as Plugins</a> model.
Expand Down
4 changes: 4 additions & 0 deletions readme.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ Features:

== Changelog ==

= 2.0.0 =
* Post meta storage mechanism simplified to use copy approach. This change updates the way meta is stored on the revision to mirror the meta on the post it is created from. props @aaemnnosttv, see https://github.com/adamsilverstein/wp-post-meta-revisions/pull/56.
NOTE: This is a breaking change - restoring revisions saved in the previous format may result in the array of values restored as a single value rather than adding a value for each item in the array. The storage of single meta values is unaffected.

= 1.0.0 =
Tagging release as 1.0.

Expand Down
43 changes: 32 additions & 11 deletions tests/test-meta-revisions.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class MetaRevisionTests extends WP_UnitTestCase {
*/
public function add_revisioned_keys( $keys ) {
$keys[] = 'meta_revision_test';
$keys[] = 'meta_multiples_test';
return $keys;
}

Expand Down Expand Up @@ -208,8 +209,9 @@ public function test_revisions_stores_meta_values() {
)
);

$revisions = wp_get_post_revisions( $post_id );
$revisions = array_values( wp_get_post_revisions( $post_id ) );
$this->assertCount( 5, $revisions );
$this->assertEquals( 'update2', get_post_meta( $revisions[0]->ID, 'meta_revision_test', true ) );

// Store custom meta values, which should now be revisioned.
update_post_meta( $post_id, 'meta_revision_test', 'update3' );
Expand Down Expand Up @@ -321,11 +323,9 @@ public function test_revisions_stores_meta_values() {
update_post_meta( $post_id, 'meta_revision_test', 'update 8', 'update 7' );
update_post_meta( $post_id, 'meta_revision_test', 'update 8 number 2', 'update 7 number 2' );
update_post_meta( $post_id, 'meta_revision_test', 'update 8 number 3', 'update 7 number 3' );
wp_update_post( array( 'ID' => $post_id ) );

// Restore the previous revision.
$revisions = wp_get_post_revisions( $post_id );
array_shift( $revisions );
$revisions = wp_get_post_revisions( $post_id );
$last_revision = array_shift( $revisions );
wp_restore_post_revision( $last_revision->ID );

Expand Down Expand Up @@ -366,12 +366,8 @@ public function test_revisions_stores_meta_values() {
// Set the test meta blank.
update_post_meta( $post_id, 'meta_revision_test', '' );

// Update to save.
wp_update_post( array( 'ID' => $post_id ) );

// Restore the previous revision.
$revisions = wp_get_post_revisions( $post_id );
array_shift( $revisions );
$revisions = wp_get_post_revisions( $post_id );
$last_revision = array_shift( $revisions );
wp_restore_post_revision( $last_revision->ID );

Expand All @@ -381,9 +377,34 @@ public function test_revisions_stores_meta_values() {
$stored_array = get_post_meta( $post_id, 'meta_revision_test' );
$this->assertEquals( $test_array, $stored_array[0] );

/*
* Test multiple revisions on the same key.
*/

// Set the test meta to the array.
add_post_meta( $post_id, 'meta_multiples_test', 'test1' );
add_post_meta( $post_id, 'meta_multiples_test', 'test2' );
add_post_meta( $post_id, 'meta_multiples_test', 'test3' );

// Update to save.
wp_update_post( array( 'ID' => $post_id ) );

$stored_array = get_post_meta( $post_id, 'meta_multiples_test' );
$expect = array( 'test1', 'test2', 'test3' );

$this->assertEquals( $expect, $stored_array );

// Restore the previous revision.
$revisions = wp_get_post_revisions( $post_id );
$last_revision = array_shift( $revisions );
wp_restore_post_revision( $last_revision->ID );

$stored_array = get_post_meta( $post_id, 'meta_multiples_test' );
$expect = array( 'test1', 'test2', 'test3' );

$this->assertEquals( $expect, $stored_array );

// Cleanup!
wp_delete_post( $original_post_id );

}

}
66 changes: 37 additions & 29 deletions wp-post-meta-revisions.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* Plugin Name: Post Meta Revisions
* Plugin URI: https://github.com/adamsilverstein/wp-post-meta-revisions
* Description: Post Meta Revisions
* Version: 1.0.0
* Version: 2.0.0
* Author: Adam Silverstein - code developed with others
* at https://core.trac.wordpress.org/ticket/20564
* License: GPLv2 or later
Expand Down Expand Up @@ -47,7 +47,7 @@ public function __construct() {
/**
* Add the revisioned meta to get_post_metadata for preview meta data.
*
* @since 4.5.0
* @since 1.0.0
*/
public function add_metadata_preview_filter() {
add_filter( 'get_post_metadata', array( $this, 'wp_preview_meta_filter' ), 10, 4 );
Expand All @@ -59,7 +59,7 @@ public function add_metadata_preview_filter() {
* Iterates thru the revisioned meta fields and checks each to see if they are set,
* and have a changed value. If so, the meta value is saved and attached to the autosave.
*
* @since 4.5.0
* @since 1.0.0
*
* @param Post object $new_autosave The new post being autosaved.
*/
Expand Down Expand Up @@ -111,15 +111,15 @@ public function wp_autosave_post_revisioned_meta_fields( $new_autosave ) {
* Determine which post meta fields should be revisioned.
*
* @access public
* @since 4.5.0
* @since 1.0.0
*
* @return array An array of meta keys to be revisioned.
*/
public function wp_post_revision_meta_keys() {
/**
* Filter the list of post meta keys to be revisioned.
*
* @since 4.5.0
* @since 1.0.0
*
* @param array $keys An array of default meta fields to be revisioned.
*/
Expand All @@ -133,7 +133,7 @@ public function wp_post_revision_meta_keys() {
* @param WP_Post $last_revision The last revision post object.
* @param WP_Post $post The post object.
*
* @since 4.5.0
* @since 1.0.0
*/
public function wp_check_revisioned_meta_fields_have_changed( $post_has_changed, WP_Post $last_revision, WP_Post $post ) {
foreach ( $this->wp_post_revision_meta_keys() as $meta_key ) {
Expand All @@ -150,21 +150,15 @@ public function wp_check_revisioned_meta_fields_have_changed( $post_has_changed,
*
* @param int $revision_id The ID of the revision to save the meta to.
*
* @since 4.5.0
* @since 1.0.0
*/
public function wp_save_revisioned_meta_fields( $revision_id ) {
$revision = get_post( $revision_id );
$post_id = $revision->post_parent;

// Save revisioned meta fields.
foreach ( $this->wp_post_revision_meta_keys() as $meta_key ) {
$meta_value = get_post_meta( $post_id, $meta_key );

/*
* Use the underlying add_metadata() function vs add_post_meta()
* to ensure metadata is added to the revision post and not its parent.
*/
add_metadata( 'post', $revision_id, $meta_key, wp_slash( $meta_value ) );
$this->copy_post_meta( $post_id, $revision_id, $meta_key );
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excellent!

}
}

Expand All @@ -174,23 +168,37 @@ public function wp_save_revisioned_meta_fields( $revision_id ) {
* @param int $post_id The ID of the post to restore the meta to.
* @param int $revision_id The ID of the revision to restore the meta from.
*
* @since 4.5.0
* @since 1.0.0
*/
public function wp_restore_post_revision_meta( $post_id, $revision_id ) {

// Restore revisioned meta fields.
$metas_revisioned = $this->wp_post_revision_meta_keys();
if ( isset( $metas_revisioned ) && 0 !== count( $metas_revisioned ) ) {
foreach ( $metas_revisioned as $meta_key ) {
// Clear any existing metas.
delete_post_meta( $post_id, $meta_key );
// Get the stored meta, not stored === blank.
$meta_values = get_post_meta( $revision_id, $meta_key, true );
if ( 0 !== count( $meta_values ) && is_array( $meta_values ) ) {
foreach ( $meta_values as $meta_value ) {
add_post_meta( $post_id, $meta_key, wp_slash( $meta_value ) );
}
}
}
foreach ( (array) $this->wp_post_revision_meta_keys() as $meta_key ) {

// Clear any existing meta.
delete_post_meta( $post_id, $meta_key );

$this->copy_post_meta( $revision_id, $post_id, $meta_key );
}
}

/**
* Copy post meta for the given key from one post to another.
*
* @param int $source_post_id Post ID to copy meta value(s) from.
* @param int $target_post_id Post ID to copy meta value(s) to.
* @param string $meta_key Meta key to copy.
*
* @since 2.0.0
*/
protected function copy_post_meta( $source_post_id, $target_post_id, $meta_key ) {

foreach ( get_post_meta( $source_post_id, $meta_key ) as $meta_value ) {
/**
* We use add_metadata() function vs add_post_meta() here
* to allow for a revision post target OR regular post.
*/
add_metadata( 'post', $target_post_id, $meta_key, wp_slash( $meta_value ) );
}
}

Expand All @@ -201,7 +209,7 @@ public function wp_restore_post_revision_meta( $post_id, $revision_id ) {
* Filters revisioned meta keys only.
*
* @access public
* @since 4.5.0
* @since 1.0.0
*
* @param mixed $value Meta value to filter.
* @param int $object_id Object ID.
Expand Down