WordPress.org

Make WordPress Core

Ticket #20564: 20564.12.diff

File 20564.12.diff, 9.9 KB (added by adamsilverstein, 6 years ago)

refresh against trunk

  • src/wp-admin/includes/post.php

     
    15271527                $new_autosave['ID'] = $old_autosave->ID;
    15281528                $new_autosave['post_author'] = $post_author;
    15291529
     1530                // Auto-save revisioned meta fields.
     1531                foreach ( _wp_post_revision_meta_keys() as $meta_key ) {
     1532                        if ( isset( $_POST[ $meta_key ] )
     1533                                && get_post_meta( $new_autosave['ID'], $meta_key, true ) != wp_unslash( $_POST[ $meta_key ] ) )
     1534                        {
     1535                                /*
     1536                                 * Use the underlying delete_metadata() and add_metadata() functions
     1537                                 * vs delete_post_meta() and add_post_meta() to make sure we're working
     1538                                 * with the actual revision meta.
     1539                                 */
     1540                                delete_metadata( 'post', $new_autosave['ID'], $meta_key );
     1541                                if ( ! empty( $_POST[ $meta_key ] ) ) {
     1542                                        add_metadata( 'post', $new_autosave['ID'], $meta_key, $_POST[ $meta_key ] );
     1543                                }
     1544                        }
     1545                }
     1546
    15301547                // If the new autosave has the same content as the post, delete the autosave.
    15311548                $post = get_post( $post_id );
    15321549                $autosave_is_different = false;
  • src/wp-includes/revision.php

     
    7070}
    7171
    7272/**
     73 * Determine which post meta fields should be revisioned.
     74 *
     75 * @access private
     76 * @since 4.0.0
     77 *
     78 * @return array An array of meta keys to be revisioned.
     79 */
     80function _wp_post_revision_meta_keys() {
     81        /**
     82         * Filter the list of post meta keys to be revisioned.
     83         *
     84         * @since 4.0.0
     85         *
     86         * @param array $keys An array of default meta fields to be revisioned.
     87         */
     88        return apply_filters( 'wp_post_revision_meta_keys', array() );
     89}
     90
     91/**
    7392 * Saves an already existing post as a post revision.
    7493 *
    7594 * Typically used immediately after post updates.
     
    127146                if ( isset( $last_revision ) && apply_filters( 'wp_save_post_revision_check_for_changes', $check_for_changes = true, $last_revision, $post ) ) {
    128147                        $post_has_changed = false;
    129148
     149                        // Check whether revisioned post fields have been changed.
    130150                        foreach ( array_keys( _wp_post_revision_fields() ) as $field ) {
    131151                                if ( normalize_whitespace( $post->$field ) != normalize_whitespace( $last_revision->$field ) ) {
    132152                                        $post_has_changed = true;
    133153                                        break;
    134154                                }
    135155                        }
    136                         //don't save revision if post unchanged
     156
     157                        // Check whether revisioned post meta fields have changed.
     158                        foreach ( _wp_post_revision_meta_keys() as $meta_key ) {
     159                                if ( get_post_meta( $post->ID, $meta_key ) != get_post_meta( $last_revision->ID, $meta_key ) ) {
     160                                        $post_has_changed = true;
     161                                        break;
     162                                }
     163                        }
     164
     165                        // Don't save revision if the post is unchanged.
    137166                        if( ! $post_has_changed )
    138167                                return;
    139168                }
     
    243272 * @return mixed WP_Error or 0 if error, new revision ID if success.
    244273 */
    245274function _wp_put_post_revision( $post = null, $autosave = false ) {
     275
    246276        if ( is_object($post) )
    247277                $post = get_object_vars( $post );
    248278        elseif ( !is_array($post) )
     
    262292        if ( is_wp_error($revision_id) )
    263293                return $revision_id;
    264294
     295
     296
    265297        if ( $revision_id ) {
    266298                /**
    267299                 * Fires once a revision has been saved.
     
    273305                do_action( '_wp_put_post_revision', $revision_id );
    274306        }
    275307
     308
     309        // Save revisioned meta fields.
     310        foreach ( _wp_post_revision_meta_keys() as $meta_key ) {
     311                $meta_value = get_post_meta( $post_id, $meta_key, true );
     312                if ( empty( $meta_value ) ) {
     313                        continue;
     314                }
     315
     316                /*
     317                 * Use the underlying add_metadata() function vs add_post_meta()
     318                 * to ensure metadata is added to the revision post and not its parent.
     319                 */
     320                add_metadata( 'post', $revision_id, $meta_key, wp_slash( $meta_value ) );
     321        }
     322
    276323        return $revision_id;
    277324}
    278325
     
    338385
    339386        $update['ID'] = $revision['post_parent'];
    340387
     388        // Restore revisioned meta fields.
     389        foreach ( _wp_post_revision_meta_keys() as $meta_key ) {
     390                $meta_value = get_post_meta( $revision['ID'], $meta_key, true );
     391                if ( empty( $meta_value ) ) {
     392                        $meta_value = '';
     393                }
     394                // Add slashes to data pulled from the database.
     395                update_post_meta( $update['ID'], $meta_key, wp_slash( $meta_value ) );
     396        }
     397
    341398        $update = wp_slash( $update ); //since data is from db
    342399
    343400        $post_id = wp_update_post( $update );
     
    505562        $post->post_excerpt = $preview->post_excerpt;
    506563
    507564        add_filter( 'get_the_terms', '_wp_preview_terms_filter', 10, 3 );
     565        add_filter( 'get_post_metadata', '_wp_preview_meta_filter', 10, 4 );
    508566
    509567        return $post;
    510568}
     
    528586}
    529587
    530588/**
     589 * Filters post meta retrieval to get values from the actual autosave post,
     590 * and not its parent.
     591 *
     592 * Filters revisioned meta keys only.
     593 *
     594 * @access private
     595 * @since 4.0.0
     596 *
     597 * @param mixed  $value     Meta value to filter.
     598 * @param int    $object_id Object ID.
     599 * @param string $meta_key  Meta key to filter a value for.
     600 * @param bool   $single    Whether to return a single value. Default false.
     601 * @return mixed Original meta value if the meta key isn't revisioned, the object doesn't exist,
     602 *               the post type is a revisionm or the post ID doesn't match the object ID.
     603 *               Otherwise, the revisioned meta value is returned for the preview.
     604 */
     605function _wp_preview_meta_filter( $value, $object_id, $meta_key, $single ) {
     606        $post = get_post();
     607        if ( empty( $post )
     608                || $post->ID != $object_id
     609                || ! in_array( $meta_key, _wp_post_revision_meta_keys() )
     610                || 'revision' == $post->post_type )
     611        {
     612                return $value;
     613        }
     614
     615        // Grab the autosave.
     616        $preview = wp_get_post_autosave( $post->ID );
     617        if ( ! is_object( $preview ) ) {
     618                return $value;
     619        }
     620
     621        return get_post_meta( $preview->ID, $meta_key, $single );
     622}
     623
     624/**
    531625 * Filters terms lookup to set the post format.
    532626 *
    533627 * @since 3.6.0
  • tests/phpunit/tests/post/revisions.php

     
    338338                        $this->assertTrue( user_can( $author_user_id, 'read_post', $revision->ID ) );
    339339                }
    340340        }
     341
     342        /**
     343         * Test the revisions system for storage of meta values
     344         * @ticket 20564
     345         */
     346        function test_revisions_stores_meta_values() {
     347                // Set up a new post
     348                $original_post_id = $post_id = $this->factory->post->create();
     349                // And update to store an initial revision
     350                wp_update_post( array( 'post_content'   => 'some initial content', 'ID' => $post_id ) );
     351
     352                // One revision so far
     353                $revisions = wp_get_post_revisions( $post_id );
     354                $this->assertCount( 1, $revisions );
     355                /**
     356                 * First set up a meta value
     357                 */
     358
     359                // Store a custom meta value, which is not revisioned by default
     360                update_post_meta( $post_id, 'meta_revision_test', 'original' );
     361
     362                // Update the post, storing a revision
     363                wp_update_post( array( 'post_content'   => 'some more content', 'ID' => $post_id ) );
     364
     365                $revisions = wp_get_post_revisions( $post_id );
     366                $this->assertCount( 2, $revisions );
     367
     368
     369                //  Next, store some updated meta values for the same key
     370                update_post_meta( $post_id, 'meta_revision_test', 'update1' );
     371
     372                // Save the post, changing content to force a revision
     373                wp_update_post( array( 'post_content'   => 'some updated content', 'ID' => $post_id ) );
     374
     375                $revisions = wp_get_post_revisions( $post_id );
     376                $this->assertCount( 3, $revisions );
     377
     378
     379                /**
     380                 * Now restore the original revision
     381                 */
     382
     383                // Restore the previous revision
     384                $revisions = (Array)wp_get_post_revisions( $post_id );
     385                // Go back two to load the previous revision
     386                array_pop( $revisions );
     387                $last_revision = array_pop( $revisions );
     388
     389                // Restore!
     390                wp_restore_post_revision( $last_revision->ID );
     391
     392                wp_update_post( array( 'ID' => $post_id ) );
     393                $revisions = wp_get_post_revisions( $post_id );
     394                $this->assertCount( 5, $revisions );
     395
     396                /**
     397                 * Check the meta values to verify they are NOT revisioned - they are not revisioned by default
     398                 */
     399
     400                // Custom post meta should NOT be restored, orignal value should not be restored, value still 'update1'
     401                $this->assertEquals( 'update1', get_post_meta( $post_id, 'meta_revision_test', true ) );
     402
     403                update_post_meta( $post_id, 'meta_revision_test', 'update2' );
     404
     405
     406                /*
     407                 * Now test the revisioning of custom meta when enabled by the wp_post_revision_meta_keys filter
     408                 */
     409
     410                // Add the custom field to be revised via the wp_post_revision_meta_keys filter
     411                add_filter( 'wp_post_revision_meta_keys', function( $keys ) {
     412                        $keys[] = 'meta_revision_test';
     413                        return $keys;
     414                });
     415
     416                // Save the post, changing content to force a revision
     417                wp_update_post( array( 'post_content'   => 'more updated content', 'ID' => $post_id ) );
     418
     419                $revisions = wp_get_post_revisions( $post_id );
     420                $this->assertCount( 6, $revisions );
     421
     422                // Store custom meta values, which should now be revisioned
     423                update_post_meta( $post_id, 'meta_revision_test', 'update3' );
     424
     425                /**
     426                 * Save the post again, custom meta should now be revisioned
     427                 *
     428                 * Note that a revision is saved even though there is no change
     429                 * in post content, becaused the revisioned post_meta has changed
     430                 *
     431                 */
     432                wp_update_post( array( 'ID' => $post_id ) );
     433
     434                // Tthis revision contains the existing post meta ('update2')
     435                $revisions = wp_get_post_revisions( $post_id );
     436                $this->assertCount( 7, $revisions );
     437
     438                // Verify that previous post meta is set
     439                $this->assertEquals( 'update3', get_post_meta( $post_id, 'meta_revision_test', true ) );
     440
     441                // Retore the previous revision
     442                $revisions = wp_get_post_revisions( $post_id );
     443
     444
     445                // Go back two to load the previous revision
     446                array_pop( $revisions );
     447                $last_revision = array_pop( $revisions );
     448                wp_restore_post_revision( $last_revision->ID );
     449
     450                // Verify that previous post meta is restored
     451                $this->assertEquals( 'update2', get_post_meta( $post_id, 'meta_revision_test', true ) );
     452
     453                // Cleanup!
     454                wp_delete_post( $original_post_id );
     455
     456        }
    341457}