WordPress.org

Make WordPress Core

Ticket #20564: 20564.10.diff

File 20564.10.diff, 11.2 KB (added by adamsilverstein, 7 years ago)

add wp_unslash to $_POST comparison

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

     
    13471347        } else {
    13481348                $post_id = (int) $post_data['post_ID'];
    13491349        }
    1350 
    13511350        $post_data = _wp_translate_postdata( true, $post_data );
    13521351        if ( is_wp_error( $post_data ) )
    13531352                return $post_data;
    13541353
    13551354        $post_author = get_current_user_id();
    1356 
    13571355        // Store one autosave per author. If there is already an autosave, overwrite it.
    13581356        if ( $old_autosave = wp_get_post_autosave( $post_id, $post_author ) ) {
    13591357                $new_autosave = _wp_post_revision_fields( $post_data, true );
    13601358                $new_autosave['ID'] = $old_autosave->ID;
    13611359                $new_autosave['post_author'] = $post_author;
    13621360
     1361                // Auto-save revisioned meta fields.
     1362                foreach ( _wp_post_revision_meta_keys() as $meta_key ) {
     1363                        if ( isset( $_POST[ $meta_key ] )
     1364                                && get_post_meta( $new_autosave['ID'], $meta_key, true ) != wp_unslash( $_POST[ $meta_key ] ) )
     1365                        {
     1366                                /*
     1367                                 * Use the underlying delete_metadata() and add_metadata() functions
     1368                                 * vs delete_post_meta() and add_post_meta() to make sure we're working
     1369                                 * with the actual revision meta.
     1370                                 */
     1371                                delete_metadata( 'post', $new_autosave['ID'], $meta_key );
     1372                                if ( ! empty( $_POST[ $meta_key ] ) ) {
     1373                                        add_metadata( 'post', $new_autosave['ID'], $meta_key, $_POST[ $meta_key ] );
     1374                                }
     1375                        }
     1376                }
     1377
    13631378                // If the new autosave has the same content as the post, delete the autosave.
    13641379                $post = get_post( $post_id );
    13651380                $autosave_is_different = false;
  • src/wp-includes/revision.php

     
    2828        if ( !$fields ) {
    2929                // Allow these to be versioned
    3030                $fields = array(
    31                         'post_title' => __( 'Title' ),
     31                        'post_title'   => __( 'Title' ),
    3232                        'post_content' => __( 'Content' ),
    3333                        'post_excerpt' => __( 'Excerpt' ),
    3434                );
    3535
    36                 // Runs only once
     36                /**
     37                 * Filter the list of post fields to be revisioned.
     38                 *
     39                 * Fields are only revisioned once.
     40                 *
     41                 * @since 3.9.0
     42                 *
     43                 * @param array $fields An array of fields to be revisioned.
     44                 */
    3745                $fields = apply_filters( '_wp_post_revision_fields', $fields );
    3846
    3947                // WP uses these internally either in versioning or elsewhere - they cannot be versioned
    40                 foreach ( array( 'ID', 'post_name', 'post_parent', 'post_date', 'post_date_gmt', 'post_status', 'post_type', 'comment_count', 'post_author' ) as $protect )
     48                foreach ( array( 'ID', 'post_name', 'post_parent', 'post_date', 'post_date_gmt', 'post_status', 'post_type', 'comment_count', 'post_author' ) as $protect ) {
    4149                        unset( $fields[$protect] );
     50                }
    4251        }
    4352
    4453        if ( !is_array($post) )
     
    5968}
    6069
    6170/**
     71 * Determine which post meta fields should be revisioned.
     72 *
     73 * @access private
     74 * @since 3.9.0
     75 *
     76 * @return array An array of meta keys to be revisioned.
     77 */
     78function _wp_post_revision_meta_keys() {
     79        /**
     80         * Filter the list of post meta keys to be revisioned.
     81         *
     82         * @since 3.9.0
     83         *
     84         * @param array $keys An array of default meta fields to be revisioned.
     85         */
     86        return apply_filters( 'wp_post_revision_meta_keys', array() );
     87}
     88
     89/**
    6290 * Saves an already existing post as a post revision.
    6391 *
    6492 * Typically used immediately after post updates.
     
    102130                if ( isset( $last_revision ) && apply_filters( 'wp_save_post_revision_check_for_changes', true, $last_revision, $post ) ) {
    103131                        $post_has_changed = false;
    104132
     133                        // Check whether revisioned post fields have been changed.
    105134                        foreach ( array_keys( _wp_post_revision_fields() ) as $field ) {
    106135                                if ( normalize_whitespace( $post->$field ) != normalize_whitespace( $last_revision->$field ) ) {
    107136                                        $post_has_changed = true;
    108137                                        break;
    109138                                }
    110139                        }
    111                         //don't save revision if post unchanged
     140
     141                        // Check whether revisioned post meta fields have changed.
     142                        foreach ( _wp_post_revision_meta_keys() as $meta_key ) {
     143                                if ( get_post_meta( $post->ID, $meta_key ) != get_post_meta( $last_revision->ID, $meta_key ) ) {
     144                                        $post_has_changed = true;
     145                                        break;
     146                                }
     147                        }
     148
     149                        // Don't save revision if the post is unchanged.
    112150                        if( ! $post_has_changed )
    113151                                return;
    114152                }
     
    240278        if ( $revision_id )
    241279                do_action( '_wp_put_post_revision', $revision_id );
    242280
     281        // Save revisioned meta fields.
     282        foreach ( _wp_post_revision_meta_keys() as $meta_key ) {
     283                $meta_value = get_post_meta( $post_id, $meta_key, true );
     284                if ( empty( $meta_value ) ) {
     285                        continue;
     286                }
     287
     288                /*
     289                 * Use the underlying add_metadata() function vs add_post_meta()
     290                 * to ensure metadata is added to the revision post and not its parent.
     291                 */
     292                add_metadata( 'post', $revision_id, $meta_key, wp_slash( $meta_value ) );
     293        }
     294
    243295        return $revision_id;
    244296}
    245297
     
    307359
    308360        $update['ID'] = $revision['post_parent'];
    309361
     362        // Restore revisioned meta fields.
     363        foreach ( _wp_post_revision_meta_keys() as $meta_key ) {
     364                $meta_value = get_post_meta( $revision['ID'], $meta_key, true );
     365                if ( empty( $meta_value ) ) {
     366                        $meta_value = '';
     367                }
     368                // Add slashes to data pulled from the database.
     369                update_post_meta( $update['ID'], $meta_key, wp_slash( $meta_value ) );
     370        }
     371
    310372        $update = wp_slash( $update ); //since data is from db
    311373
    312374        $post_id = wp_update_post( $update );
     
    448510        $post->post_excerpt = $preview->post_excerpt;
    449511
    450512        add_filter( 'get_the_terms', '_wp_preview_terms_filter', 10, 3 );
     513        add_filter( 'get_post_metadata', '_wp_preview_meta_filter', 10, 4 );
    451514
    452515        return $post;
    453516}
     
    471534}
    472535
    473536/**
     537 * Filters post meta retrieval to get values from the actual autosave post,
     538 * and not its parent.
     539 *
     540 * Filters revisioned meta keys only.
     541 *
     542 * @access private
     543 * @since 3.9.0
     544 *
     545 * @param mixed  $value     Meta value to filter.
     546 * @param int    $object_id Object ID.
     547 * @param string $meta_key  Meta key to filter a value for.
     548 * @param bool   $single    Whether to return a single value. Default false.
     549 * @return mixed Original meta value if the meta key isn't revisioned, the object doesn't exist,
     550 *               the post type is a revisionm or the post ID doesn't match the object ID.
     551 *               Otherwise, the revisioned meta value is returned for the preview.
     552 */
     553function _wp_preview_meta_filter( $value, $object_id, $meta_key, $single ) {
     554        $post = get_post();
     555        if ( empty( $post )
     556                || $post->ID != $object_id
     557                || ! in_array( $meta_key, _wp_post_revision_meta_keys() )
     558                || 'revision' == $post->post_type )
     559        {
     560                return $value;
     561        }
     562
     563        // Grab the autosave.
     564        $preview = wp_get_post_autosave( $post->ID );
     565        if ( ! is_object( $preview ) ) {
     566                return $value;
     567        }
     568
     569        return get_post_meta( $preview->ID, $meta_key, $single );
     570}
     571
     572/**
    474573 * Filters terms lookup to set the post format.
    475574 *
    476575 * @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                // Two revisions so far
     366                $revisions = wp_get_post_revisions( $post_id );
     367                $this->assertCount( 2, $revisions );
     368
     369
     370                //  Next, store some updated meta values for the same key
     371                update_post_meta( $post_id, 'meta_revision_test', 'update1' );
     372
     373                // Save the post, changing content to force a revision
     374                wp_update_post( array( 'post_content'   => 'some updated content', 'ID' => $post_id ) );
     375
     376                // Three revisions so far
     377                $revisions = wp_get_post_revisions( $post_id );
     378                $this->assertCount( 3, $revisions );
     379
     380
     381                /**
     382                 * Now restore the original revision
     383                 */
     384
     385                // Restore the previous revision
     386                $revisions = (Array)wp_get_post_revisions( $post_id );
     387                // Go back two to load the previous revision
     388                array_shift( $revisions );
     389                $last_revision = array_shift( $revisions );
     390
     391                // Restore!
     392                wp_restore_post_revision( $last_revision->ID );
     393
     394                wp_update_post( array( 'ID' => $post_id ) );
     395                $revisions = wp_get_post_revisions( $post_id );
     396                $this->assertCount( 4, $revisions );
     397
     398                /**
     399                 * Check the meta values to verify they are NOT revisioned - they are not revisioned by default
     400                 */
     401
     402                // Custom post meta should NOT be restored, orignal value should not be restored, value still 'update1'
     403                $this->assertEquals( 'update1', get_post_meta( $post_id, 'meta_revision_test', true ) );
     404
     405                update_post_meta( $post_id, 'meta_revision_test', 'update2' );
     406
     407                // Verify revision no saved when nothing has changed
     408                wp_update_post( array( 'ID' => $post_id ) );
     409                $revisions = wp_get_post_revisions( $post_id );
     410                $this->assertCount( 4, $revisions );
     411
     412                /*
     413                 * Now test the revisioning of custom meta when enabled by the wp_post_revision_meta_keys filter
     414                 */
     415
     416                // Add the custom field to be revised via the wp_post_revision_meta_keys filter
     417                add_filter( 'wp_post_revision_meta_keys', function( $keys ) {
     418                        $keys[] = 'meta_revision_test';
     419                        return $keys;
     420                });
     421
     422                // Save the post, changing content to force a revision
     423                wp_update_post( array( 'post_content'   => 'more updated content', 'ID' => $post_id ) );
     424
     425                // Five revisions so far
     426                $revisions = wp_get_post_revisions( $post_id );
     427                $this->assertCount( 5, $revisions );
     428
     429                // Store custom meta values, which should now be revisioned
     430                update_post_meta( $post_id, 'meta_revision_test', 'update3' );
     431
     432                /**
     433                 * Save the post again, custom meta should now be revisioned
     434                 *
     435                 * Note that a revision is saved even though there is no change
     436                 * in post content, becaused the revisioned post_meta has changed
     437                 *
     438                 */
     439                wp_update_post( array( 'ID' => $post_id ) );
     440
     441                // Six revisions so far, this revision contains the existing post meta ('update2')
     442                $revisions = wp_get_post_revisions( $post_id );
     443                $this->assertCount( 6, $revisions );
     444
     445                // Verify that previous post meta is set
     446                $this->assertEquals( 'update3', get_post_meta( $post_id, 'meta_revision_test', true ) );
     447
     448                // Retore the previous revision
     449                $revisions = wp_get_post_revisions( $post_id );
     450                // Go back two to load the previous revision
     451                array_shift( $revisions );
     452                $last_revision = array_shift( $revisions );
     453                wp_restore_post_revision( $last_revision->ID );
     454
     455                // Verify that previous post meta is restored
     456                $this->assertEquals( 'update2', get_post_meta( $post_id, 'meta_revision_test', true ) );
     457
     458                // Cleanup!
     459                wp_delete_post( $original_post_id );
     460
     461        }
    341462}