WordPress.org

Make WordPress Core

Ticket #43760: 43760.1.diff

File 43760.1.diff, 5.0 KB (added by soulseekah, 3 years ago)

diff-based implementation

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

    diff --git src/wp-admin/includes/post.php src/wp-admin/includes/post.php
    index 67ce58c..7639d08 100644
    function wp_create_post_autosave( $post_data ) { 
    17801780                        return 0;
    17811781                }
    17821782
     1783                // Add a revision if the content is significantly different.
     1784                wp_create_revision_for_autosave( $old_autosave, $new_autosave );
     1785
    17831786                /**
    17841787                 * Fires before an autosave is stored.
    17851788                 *
    function wp_autosave( $post_data ) { 
    18941897        }
    18951898
    18961899        if ( ! wp_check_post_lock( $post->ID ) && get_current_user_id() == $post->post_author && ( 'auto-draft' == $post->post_status || 'draft' == $post->post_status ) ) {
     1900                // Add a revision if the content is significantly different.
     1901                wp_create_revision_for_autosave( $post, wp_slash( $post_data ) );
     1902
    18971903                // Drafts and auto-drafts are just overwritten by autosave for the same user if the post is not locked
    18981904                return edit_post( wp_slash( $post_data ) );
    18991905        } else {
  • src/wp-includes/revision.php

    diff --git src/wp-includes/revision.php src/wp-includes/revision.php
    index bc95631..6259581 100644
    function _wp_upgrade_revisions_of_post( $post, $revisions ) { 
    768768
    769769        return true;
    770770}
     771
     772/**
     773 * Create a revision when the autosave content is significantly different.
     774 *
     775 * If the autosave content is significantly different from the current post or the previous autosave,
     776 * create a revision from the old data.
     777 *
     778 * @since 5.0.0
     779 *
     780 * @param WP_Post $post          The current post or the previous autosave revision.
     781 * @param array   $autosave_data The autosave data.
     782 */
     783function wp_create_revision_for_autosave( $post, $autosave_data ) {
     784
     785        if ( ! wp_revisions_enabled( $post ) ) {
     786                return;
     787        }
     788
     789        $post_data = get_object_vars( $post );
     790
     791        if ( $post_data['post_type'] === 'revision' ) {
     792                // If the old post is a revision, need to merge it with the actual post.
     793                $parent_post = $this->get_parent( $post_data['post_parent'] );
     794                foreach ( array_keys( _wp_post_revision_fields( $parent_post ) ) as $field ) {
     795                        if ( isset( $post_data[ $field ] ) ) {
     796                                $parent_post->$field = $post_data[ $field ];
     797                        }
     798                }
     799                $post_data = get_object_vars( $parent_post );
     800        }
     801
     802
     803        if ( ! class_exists( 'Text_Diff', false ) ) {
     804                require( ABSPATH . WPINC . '/wp-diff.php' );
     805        }
     806
     807        $left_lines  = explode( "\n", $post_data['post_content'] );
     808        $right_lines = explode( "\n", $autosave_data['post_content'] );
     809
     810        $diff = new Text_Diff( $left_lines, $right_lines );
     811
     812        $total_lines   = count( $left_lines );
     813        $edits         = array_map( 'get_class', $diff->getDiff() );
     814        $changed_lines = count( $edits );
     815        $counts        = array_count_values( $edits );
     816        if ( ! empty( $counts['Text_Diff_Op_copy'] ) ) {
     817                $changed_lines -= $counts['Text_Diff_Op_copy'];
     818        }
     819
     820        /**
     821         * Filter the change percentage threshold.
     822         *
     823         * @since 5.0.0
     824         *
     825         * @param int $percent_changed_threshold The threshold percentage.
     826         * @param int $post_data                 The current post data.
     827         */
     828        $percent_changed_threshold = apply_filters( 'wp_create_revision_for_autosave_threshold', 25, $post_data );
     829       
     830        $percent_changed = ( $changed_lines / $total_lines ) * 100;
     831        $create_revision = $percent_changed > $percent_changed_threshold;
     832
     833        /**
     834         * Filter whether a revision is created when an autosave is made via the REST API.
     835         *
     836         * @since 5.0.0
     837         *
     838         * @param bool  $create_revision Create a revision?
     839         * @param array $post_data       The current post data.
     840         * @param array $autosave_data   The calculated autosave difference.
     841         */
     842        if ( apply_filters( 'wp_create_revision_for_autosave', $create_revision, $post_data, $autosave_data ) ) {
     843                _wp_put_post_revision( $post_data );
     844        }
     845}
  • tests/phpunit/tests/post/revisions.php

    diff --git tests/phpunit/tests/post/revisions.php tests/phpunit/tests/post/revisions.php
    index 5b79e4b..0094ecc 100644
    class Tests_Post_Revisions extends WP_UnitTestCase { 
    576576
    577577                $this->assertEquals( $revision_ids, array_values( wp_list_pluck( $revisions, 'ID' ) ) );
    578578        }
     579
     580        /**
     581         * @ticket 43760
     582         *
     583         * @dataProvider get_test_wp_create_revision_for_autosave
     584         */
     585        public function test_wp_create_revision_for_autosave( $post_content, $autosave_data, $revision ) {
     586                $post = self::factory()->post->create_and_get(
     587                        array(
     588                                'post_type'    => 'post',
     589                                'post_content' => $post_content,
     590                        )
     591                );
     592
     593                $post_data = array(
     594                        'post_content' => $autosave_data,
     595                );
     596
     597                wp_create_revision_for_autosave( $post, $post_data );
     598
     599                $revisions = wp_get_post_revisions( $post->ID );
     600                $this->assertTrue( ! ( count( $revisions ) xor $revision ) );
     601        }
     602
     603        public function get_test_wp_create_revision_for_autosave() {
     604                return array(
     605                        array(
     606                                "some content\nmore content",
     607                                "some content\nwhat content",
     608                                true,
     609                        ),
     610                        array(
     611                                "some content\nmore content",
     612                                "some content",
     613                                true,
     614                        ),
     615                        array(
     616                                "some content\nhello world\nwhere is\nthe diff",
     617                                "some content\nhello world\nwhere is\nthe diffs",
     618                                false,
     619                        ),
     620                );
     621        }
    579622}