WordPress.org

Make WordPress Core

Ticket #16215: 16215-14.patch

File 16215-14.patch, 12.1 KB (added by azaozz, 5 years ago)
  • wp-includes/post-template.php

     
    14241424
    14251425        // Since 3.6 revisions include a copy of the current post data as a revision.
    14261426        // The following removes that revision when $parent == false
    1427         $parent_included = wp_first_revision_matches_current_version( $post_id );
     1427        $parent_included = _wp_last_revision_matches_current_post( $post_id );
    14281428        if ( $parent_included && ! $parent )
    14291429                array_pop( $revisions );
    14301430        elseif ( ! $parent_included && $parent )
  • wp-includes/revision.php

     
    6363/**
    6464 * Saves an already existing post as a post revision.
    6565 *
    66  * Typically used immediately prior and after post updates.
    67  * Prior to update checks for old revision data (latest revision != current post before update) and adds a copy of the current post as a revision if missing
    68  * After update adds a copy of the current post as a revision, so latest revision always matches current post
     66 * Typically used immediately after post updates.
     67 * Adds a copy of the current post as a revision, so latest revision always matches current post
    6968 *
    7069 * @package WordPress
    7170 * @subpackage Post_Revisions
    7271 * @since 2.6.0
    7372 *
    7473 * @uses _wp_put_post_revision()
    75  * @uses wp_first_revision_matches_current_version()
    7674 *
    7775 * @param int $post_id The ID of the post to save as a revision.
    7876 * @return mixed Null or 0 if error, new revision ID, if success.
    7977 */
    8078function wp_save_post_revision( $post_id ) {
    81         //check to see if the post's first revision already matches the post data
    82         //should be true before post update, _except_ for old data which
    83         //doesn't include a copy of the current post data in revisions
    84         if ( wp_first_revision_matches_current_version( $post_id ) )
    85                 return;
    86 
    8779        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
    8880                return;
    8981
    90         if ( ! $post = get_post( $post_id, ARRAY_A ) )
     82        if ( ! $post = get_post( $post_id ) )
    9183                return;
    9284
    93         if ( ! wp_revisions_enabled( (object) $post ) )
     85        if ( ! post_type_supports( $post->post_type, 'revisions' ) )
    9486                return;
    9587
    96         if ( 'auto-draft' == $post['post_status'] )
     88        if ( 'auto-draft' == $post->post_status )
    9789                return;
    9890
    99         if ( ! post_type_supports( $post['post_type'], 'revisions' ) )
     91        if ( ! wp_revisions_enabled( $post ) )
    10092                return;
    10193
    102         // compare the proposed update with the last stored revision, verify
    103         // different, unless a plugin tells us to always save regardless
     94        // Compare the proposed update with the last stored revision verifying that
     95        // they are different, unless a plugin tells us to always save regardless.
     96        // If no previous revisions, save one
    10497        if ( $revisions = wp_get_post_revisions( $post_id ) ) {
    105                 // grab the last revision
    106                 $last_revision = array_shift( $revisions );
     98                // grab the last revision, but not an autosave
     99                foreach ( $revisions as $revision ) {
     100                        if ( false !== strpos( $revision->post_name, "{$revision->post_parent}-revision" ) ) {
     101                                $last_revision = $revision;
     102                                break;
     103                        }
     104                }
    107105
    108                 //if no previous revisions, save one for sure
    109                 if ( $last_revision_array = get_post( $last_revision->ID, ARRAY_A ) ) {
     106                if ( isset( $last_revision ) && apply_filters( 'wp_save_post_revision_check_for_changes', true, $last_revision, $post ) ) {
     107                        $post_has_changed = false;
    110108
    111                         if ( apply_filters( 'wp_save_post_revision_check_for_changes', true, $last_revision_array, $post ) && is_array( $post ) ) {
    112                                 $post_has_changed = false;
    113 
    114                                 foreach ( array_keys( _wp_post_revision_fields() ) as $field ) {
    115 
    116                                         if ( normalize_whitespace( $post[ $field ] ) != normalize_whitespace( $last_revision_array[ $field ] ) ) {
    117                                                 $post_has_changed = true;
    118                                                 break;
    119 
    120                                         }
     109                        foreach ( array_keys( _wp_post_revision_fields() ) as $field ) {
     110                                if ( normalize_whitespace( $post->$field ) != normalize_whitespace( $last_revision->$field ) ) {
     111                                        $post_has_changed = true;
     112                                        break;
    121113                                }
     114                        }
    122115
    123                                 //don't save revision if post unchanged
    124                                 if( ! $post_has_changed )
    125                                         return;
    126                         }
     116                        //don't save revision if post unchanged
     117                        if( ! $post_has_changed )
     118                                return;
    127119                }
    128120        }
    129121
    130122        $return = _wp_put_post_revision( $post );
    131123
    132         $revisions_to_keep = wp_revisions_to_keep( (object) $post );
     124        $revisions_to_keep = wp_revisions_to_keep( $post );
    133125
    134126        if ( $revisions_to_keep < 0 )
    135127                return $return;
    136128
    137         // all revisions and (possibly) one autosave
     129        // all revisions and autosaves
    138130        $revisions = wp_get_post_revisions( $post_id, array( 'order' => 'ASC' ) );
    139131
    140132        $delete = count($revisions) - $revisions_to_keep;
     
    144136
    145137        $revisions = array_slice( $revisions, 0, $delete );
    146138
    147         for ( $i = 0; isset($revisions[$i]); $i++ ) {
     139        for ( $i = 0; isset( $revisions[$i] ); $i++ ) {
    148140                if ( false !== strpos( $revisions[ $i ]->post_name, 'autosave' ) )
    149141                        continue;
     142
    150143                wp_delete_post_revision( $revisions[ $i ]->ID );
    151144        }
    152145
     
    444437        return (int) apply_filters( 'wp_revisions_to_keep', $num, $post );
    445438}
    446439
    447 
    448440function _set_preview($post) {
    449441
    450442        if ( ! is_object($post) )
     
    464456        return $post;
    465457}
    466458
    467 function _wp_get_post_revision_version( $post ) {
    468         if ( is_array( $post ) ) {
    469                 if ( ! isset( $post['post_name'] ) ) {
    470                         return false;
    471                 }
    472 
    473                 $name = $post['post_name'];
    474         } elseif ( is_object( $post ) ) {
    475                 if ( ! isset( $post->post_name ) ) {
    476                         return false;
    477                 }
    478 
    479                 $name = $post->post_name;
    480         } else {
     459function _wp_get_post_revision_version( $revision ) {
     460        if ( is_object( $revision ) )
     461                $revision = get_object_vars( $revision );
     462        elseif ( !is_array( $revision ) )
    481463                return false;
    482         }
    483464
    484         if ( ! preg_match( '/^(\d+-)(?:autosave|revision)(?:-v)(\d+)$/', $name, $matches ) ) {
    485                 return 0;
    486         }
     465        if ( preg_match( '/^\d+-(?:autosave|revision)-v(\d+)$/', $revision['post_name'], $matches ) )
     466                return (int) $matches[1];
    487467
    488         if ( '1' === $matches[2] ) {
    489                 return 1;
    490         }
    491 
    492468        return 0;
    493469}
    494470
     
    502478 * @uses get_post()
    503479 * @uses post_type_supports()
    504480 * @uses wp_get_post_revisions()
    505  * @uses wp_save_post_revision()
    506481 *
    507482 * @param int|object $post_id Post ID or post object
    508483 * @return true if success, false if problems
     
    514489        if ( ! $post )
    515490                return false;
    516491
    517         //make sure we have a current revision, only adds one if missing
    518         wp_save_post_revision( $post->ID );
    519 
    520492        if ( ! post_type_supports( $post->post_type, 'revisions' ) )
    521493                return false;
    522494
    523495        $revisions = wp_get_post_revisions( $post->ID ); // array( 'order' => 'DESC', 'orderby' => 'date' ); // Always work from most recent to oldest
    524496
     497        if ( ! $first = reset( $revisions ) )
     498                return true;
    525499
    526         if ( ! $revisions )
     500        // Check if the revisions have already been updated
     501        if ( preg_match( '/^\d+-(?:autosave|revision)-v\d+$/', $first->post_name ) )
    527502                return true;
    528503
    529504        // Add post option exclusively
    530         $lock      = "revision-upgrade-{$post->ID}";
    531         $locked_at = number_format( microtime( true ), 10, '.', '' );
    532         $result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, 'no') /* LOCK */", $lock, $locked_at ) );
     505        $lock = "revision-upgrade-{$post->ID}";
     506        $now = time();
     507        $result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, 'no') /* LOCK */", $lock, $now ) );
    533508        if ( ! $result ) {
    534509                // If we couldn't get a lock, see how old the previous lock is
    535                 $locked_at = get_option( $lock );
    536                 if ( !$locked_at ) {
     510                $locked = get_option( $lock );
     511                if ( ! $locked ) {
    537512                        // Can't write to the lock, and can't read the lock.
    538513                        // Something broken has happened
    539514                        return false;
    540515                }
    541516
    542                 if ( $lock_at < number_format( microtime( true ), 10, '.', '' ) - 3600 ) {
    543                         // Lock is too old - try again
    544                         delete_option( $lock );
    545                         return wp_upgrade_revisions_of_post( $post );
     517                if ( $locked > $now - 3600 ) {
     518                        // Lock is not too old: some other process may be upgrading this post.  Bail.
     519                        return false;
    546520                }
    547521
    548                 // Lock is not too old: some other process may be upgrading this post.  Bail.
    549                 return;
    550         } else {
    551                 // If we could get a lock, re-"add" the option to fire all the correct filters.
    552                 add_option( $lock, $locked_at );
     522                // Lock is too old - update it (below) and continue
    553523        }
    554524
    555         $success = true;
     525        // If we could get a lock, re-"add" the option to fire all the correct filters.
     526        update_option( $lock, $now );
    556527
    557528        reset( $revisions );
     529
    558530        do {
    559531                $this_revision = current( $revisions );
    560532                $prev_revision = next( $revisions );
    561533
    562534                $this_revision_version = _wp_get_post_revision_version( $this_revision );
    563535
    564                 error_log($this_revision_version);
    565 
    566536                // Something terrible happened
    567537                if ( false === $this_revision_version )
    568538                        continue;
     
    571541                if ( 0 < $this_revision_version )
    572542                        continue;
    573543
    574                 // This revision is the oldest revision of the post.
    575                 // The correct post_author is probably $post->post_author, but that's only a good guess.
    576                 // Leave un-upgraded.
    577                 if ( ! $prev_revision ) {
    578                         continue;
    579                 }
     544                // Always update the revision version
     545                $update = array(
     546                        'post_name' => preg_replace( '/^(\d+-(?:autosave|revision))[\d-]*$/', '$1-v1', $this_revision->post_name ),
     547                );
    580548
    581                 $prev_revision_version = _wp_get_post_revision_version( $prev_revision );
     549                // If this revision is the oldest revision of the post, i.e. no $prev_revision,
     550                // the correct post_author is probably $post->post_author, but that's only a good guess.
     551                // Update the revision version only and Leave the author as-is.
     552                if ( $prev_revision ) {
     553                        $prev_revision_version = _wp_get_post_revision_version( $prev_revision );
    582554
    583                 // If the previous revision is already up to date, it no longer has the information we need :(
    584                 if ( 0 < $prev_revision_version ) {
    585                         continue;
     555                        // If the previous revision is already up to date, it no longer has the information we need :(
     556                        if ( $prev_revision_version < 1 )
     557                                $update['post_author'] = $prev_revision->post_author;
    586558                }
    587559
    588560                // Upgrade this revision
    589                 // Cast as object so that wp_update_post() handles slashing for us
    590                 $update = (object) array(
    591                         'ID'          => $this_revision->ID,
    592                         'post_name'   => preg_replace( '/^(\d+-)(autosave|revision)-(\d+)$/', '$1$2-v1', $this_revision->post_name ),
    593                         'post_author' => $prev_revision->post_author,
    594                 );
    595                 //error_log(json_encode($update));
    596                 $result = wp_update_post( $update );
    597                 if ( ! $result || is_wp_error( $result ) ) {
    598                         // Wilhelm!
    599                         $success = false;
    600                         break;
    601                 }
     561                $result = $wpdb->update( $wpdb->posts, $update, array( 'ID' => $this_revision->ID ) );
     562
     563                if ( $result )
     564                        wp_cache_delete( $this_revision->ID, 'posts' );
     565
    602566        } while ( $prev_revision );
    603567
    604568        delete_option( $lock );
    605         return true;
     569       
     570        // Add a copy of the post as latest revision.
     571        wp_save_post_revision( $post->ID );
     572        return $success;
    606573}
    607574
    608575
     
    628595 * @param int|object $post Post ID or post object.
    629596 * @return bool false if not a match, otherwise true.
    630597 */
    631 function wp_first_revision_matches_current_version( $post ) {
    632 
     598function _wp_last_revision_matches_current_post( $post ) {
    633599        if ( ! $post = get_post( $post ) )
    634600                return false;
    635601
    636602        if ( ! $revisions = wp_get_post_revisions( $post->ID ) )
    637603                return false;
    638604
    639         $last_revision = array_shift( $revisions );
     605        foreach ( $revisions as $revision ) {
     606                if ( false !== strpos( $revision->post_name, "{$revision->post_parent}-revision" ) ) {
     607                        $last_revision = $revision;
     608                        break;
     609                }
     610        }
    640611
    641         if ( ! ($last_revision->post_modified == $post->post_modified ) )
     612        // No revisions yet, only autosaves
     613        if ( ! isset( $last_revision ) )
    642614                return false;
    643615
    644         return true;
     616        $post_has_changed = false;
     617        if ( $last_revision->post_modified == $post->post_modified ) {
     618                foreach ( array_keys( _wp_post_revision_fields() ) as $field ) {
     619                        if ( normalize_whitespace( $post->$field ) != normalize_whitespace( $last_revision->$field ) ) {
     620                                $post_has_changed = true;
     621                                break;
     622                        }
     623                }
     624        } else {
     625                return false;
     626        }
     627
     628        return ! $post_has_changed;
    645629}
    646630
    647631/**
     
    706690        $r .= "</table>";
    707691
    708692        return array( 'html' => $r, 'linesadded' => $linesadded, 'linesdeleted' => $linesdeleted );
    709         }
     693}