WordPress.org

Make WordPress Core

Ticket #16215: 16215.8.diff

File 16215.8.diff, 15.9 KB (added by adamsilverstein, 13 months ago)

fixes old data on the fly, add current post as revision on 1st update

  • wp-includes/default-filters.php

     
    250250add_action( 'plugins_loaded',             'wp_maybe_load_widgets',                    0    ); 
    251251add_action( 'plugins_loaded',             'wp_maybe_load_embeds',                     0    ); 
    252252add_action( 'shutdown',                   'wp_ob_end_flush_all',                      1    ); 
    253 add_action( 'pre_post_update',            'wp_save_post_revision',                   10, 2 ); 
     253add_action( 'pre_post_update',            'wp_save_post_revision',                   10, 1 ); 
     254add_action( 'post_updated',               'wp_save_post_revision',                   10, 1 ); 
    254255add_action( 'publish_post',               '_publish_post_hook',                       5, 1 ); 
    255256add_action( 'transition_post_status',     '_transition_post_status',                  5, 3 ); 
    256257add_action( 'transition_post_status',     '_update_term_count_on_transition_post_status', 10, 3 ); 
  • wp-includes/post-template.php

     
    13451345        if ( !in_array( $revision->post_type, array( 'post', 'page', 'revision' ) ) ) 
    13461346                return false; 
    13471347 
    1348         $author = get_the_author_meta( 'display_name', $revision->post_author ); 
     1348        $author = get_the_modified_author( $revision->ID ); 
    13491349        /* translators: revision date format, see http://php.net/date */ 
    13501350        $datef = _x( 'j F, Y @ G:i:s', 'revision date format'); 
    13511351 
  • wp-includes/post.php

     
    28222822                $wpdb->update( $wpdb->posts, array( 'post_name' => $data['post_name'] ), $where ); 
    28232823        } 
    28242824 
     2825        if ( 'revision' !== $post_type ) 
     2826                update_post_meta( $post_ID, '_edit_last', $user_ID ); 
     2827 
    28252828        if ( is_object_in_taxonomy($post_type, 'category') ) 
    28262829                wp_set_post_categories( $post_ID, $post_category ); 
    28272830 
  • wp-includes/revision.php

     
    5252        $return['post_parent']   = $post['ID']; 
    5353        $return['post_status']   = 'inherit'; 
    5454        $return['post_type']     = 'revision'; 
    55         $return['post_name']     = $autosave ? "$post[ID]-autosave" : "$post[ID]-revision"; 
     55        $return['post_name']     = $autosave ? "$post[ID]-1-autosave" : "$post[ID]-1-revision"; // "1" is the revisioning system version 
    5656        $return['post_date']     = isset($post['post_modified']) ? $post['post_modified'] : ''; 
    5757        $return['post_date_gmt'] = isset($post['post_modified_gmt']) ? $post['post_modified_gmt'] : ''; 
     58        $return['post_author']   = get_post_meta( $post['ID'], '_edit_last', true ); 
    5859 
    5960        return $return; 
    6061} 
     
    6263/** 
    6364 * Saves an already existing post as a post revision. 
    6465 * 
    65  * Typically used immediately prior to post updates. 
     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 
    6669 * 
    6770 * @package WordPress 
    6871 * @subpackage Post_Revisions 
    6972 * @since 2.6.0 
    7073 * 
    7174 * @uses _wp_put_post_revision() 
     75 * @uses wp_first_revision_matches_current_version() 
    7276 * 
    7377 * @param int $post_id The ID of the post to save as a revision. 
    7478 * @return mixed Null or 0 if error, new revision ID, if success. 
    7579 */ 
    76 function wp_save_post_revision( $post_id, $new_data = null ) { 
    77         // We do autosaves manually with wp_create_post_autosave() 
     80function 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 
    7887        if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) 
    7988                return; 
    8089 
     
    8291        if ( ! WP_POST_REVISIONS ) 
    8392                return; 
    8493 
    85         if ( !$post = get_post( $post_id, ARRAY_A ) ) 
     94        if ( ! $post = get_post( $post_id, ARRAY_A ) ) 
    8695                return; 
    8796 
    8897        if ( 'auto-draft' == $post['post_status'] ) 
    8998                return; 
    9099 
    91         if ( !post_type_supports($post['post_type'], 'revisions') ) 
     100        if ( ! post_type_supports( $post['post_type'], 'revisions' ) ) 
    92101                return; 
    93102 
    94         // if new data is supplied, check that it is different from last saved revision, unless a plugin tells us to always save regardless 
    95         if ( apply_filters( 'wp_save_post_revision_check_for_changes', true, $post, $new_data ) && is_array( $new_data ) ) { 
    96                 $post_has_changed = false; 
    97                 foreach ( array_keys( _wp_post_revision_fields() ) as $field ) { 
    98                         if ( normalize_whitespace( $new_data[ $field ] ) != normalize_whitespace( $post[ $field ] ) ) { 
    99                                 $post_has_changed = true; 
    100                                 break; 
     103        // compare the proposed update with the last stored revision, verify 
     104        // different, unless a plugin tells us to always save regardless 
     105        if ( $revisions = wp_get_post_revisions( $post_id ) ) { // grab the last revision 
     106                $last_revision = array_shift( $revisions ); 
     107 
     108                if ( $last_revision_array = get_post( $last_revision->ID, ARRAY_A ) ) { //if no previous revisions, save one for sure 
     109 
     110                        if ( apply_filters( 'wp_save_post_revision_check_for_changes', true, $last_revision_array, $post ) && is_array( $post ) ) { 
     111                                $post_has_changed = false; 
     112 
     113                                foreach ( array_keys( _wp_post_revision_fields() ) as $field ) { 
     114 
     115                                        if ( normalize_whitespace( $post[ $field ] ) != normalize_whitespace( $last_revision_array[ $field ] ) ) { 
     116                                                $post_has_changed = true; 
     117                                                break; 
     118 
     119                                        } 
     120                                } 
     121 
     122                                //don't save revision if post unchanged 
     123                                if( ! $post_has_changed ) 
     124                                        return; 
    101125                        } 
    102126                } 
    103                 //don't save revision if post unchanged 
    104                 if( ! $post_has_changed ) 
    105                         return; 
    106127        } 
    107128 
    108129        $return = _wp_put_post_revision( $post ); 
    109130 
    110131        // WP_POST_REVISIONS = true (default), -1 
    111         if ( !is_numeric( WP_POST_REVISIONS ) || WP_POST_REVISIONS < 0 ) 
     132        if ( ! is_numeric( WP_POST_REVISIONS ) || WP_POST_REVISIONS < 0 ) 
    112133                return $return; 
    113134 
    114135        // all revisions and (possibly) one autosave 
    115136        $revisions = wp_get_post_revisions( $post_id, array( 'order' => 'ASC' ) ); 
    116137 
    117138        // WP_POST_REVISIONS = (int) (# of autosaves to save) 
    118         $delete = count($revisions) - WP_POST_REVISIONS; 
     139        $delete = count( $revisions ) - WP_POST_REVISIONS; 
    119140 
    120141        if ( $delete < 1 ) 
    121142                return $return; 
     
    123144        $revisions = array_slice( $revisions, 0, $delete ); 
    124145 
    125146        for ( $i = 0; isset($revisions[$i]); $i++ ) { 
    126                 if ( false !== strpos( $revisions[$i]->post_name, 'autosave' ) ) 
     147                if ( false !== strpos( $revisions[ $i ]->post_name, 'autosave' ) ) 
    127148                        continue; 
    128                 wp_delete_post_revision( $revisions[$i]->ID ); 
     149                wp_delete_post_revision( $revisions[ $i ]->ID ); 
    129150        } 
    130151 
    131152        return $return; 
     
    142163 * @subpackage Post_Revisions 
    143164 * @since 2.6.0 
    144165 * @uses wp_get_post_revisions() 
    145  *   
     166 * 
    146167 * @param int $post_id The post ID. 
    147168 * @param int $user_id optional The post author ID. 
    148169 * @return object|bool The autosaved data or false on failure or when no autosave exists. 
     
    393414        return $post; 
    394415} 
    395416 
     417function _wp_get_post_revision_version( $post ) { 
     418        if ( is_array( $post ) ) { 
     419                if ( ! isset( $post['post_name'] ) ) { 
     420                        return false; 
     421                } 
     422 
     423                $name = $post['post_name']; 
     424        } elseif ( is_object( $post ) ) { 
     425                if ( ! isset( $post->post_name ) ) { 
     426                        return false; 
     427                } 
     428 
     429                $name = $post->post_name; 
     430        } else { 
     431                return false; 
     432        } 
     433 
     434        if ( ! preg_match( '/^([\d-]+)(?:autosave|revision)(?:-\d+)*$/', $name, $matches ) ) { 
     435                return false; 
     436        } 
     437 
     438        $parts = explode( '-', trim( $matches[1], '-' ) ); 
     439 
     440        if ( 2 !== count( $parts ) ) { 
     441                return 0; 
     442        } 
     443 
     444        return (int) $parts[1]; 
     445} 
     446 
     447function _wp_upgrade_revisions_of_post( $post ) { 
     448        global $wpdb; 
     449 
     450        $post = get_post( $post ); 
     451        if ( ! $post ) 
     452                return false; 
     453 
     454        if ( ! post_type_supports( $post->post_type, 'revisions' ) ) 
     455                return false; 
     456 
     457        $revisions = wp_get_post_revisions( $post->ID ); // array( 'order' => 'DESC', 'orderby' => 'date' ); // Always work from most recent to oldest 
     458 
     459        if ( ! $revisions ) 
     460                return true; 
     461 
     462        // Add post option exclusively 
     463        $lock      = "revision-upgrade-{$post->ID}"; 
     464        $locked_at = time(); 
     465        $result = $wpdb->query( $wpdb->prepare( "INSERT IGNORE INTO `$wpdb->options` (`option_name`, `option_value`, `autoload`) VALUES (%s, %s, 'no') /* LOCK */", $lock, $locked_at ) ); 
     466        if ( ! $result ) { 
     467                // If we couldn't get a lock, see how old the previous lock is 
     468                $locked_at = get_option( $lock ); 
     469                if ( !$locked_at ) { 
     470                        // Can't write to the lock, and can't read the lock. 
     471                        // Something broken has happened 
     472                        return false; 
     473                } 
     474 
     475                if ( $lock_at < time() - 3600 ) { 
     476                        // Lock is too old - try again 
     477                        delete_option( $lock ); 
     478                        return wp_upgrade_revisions_of_post( $post ); 
     479                } 
     480 
     481                // Lock is not too old: some other process may be upgrading this post.  Bail. 
     482                return; 
     483        } else { 
     484                // If we could get a lock, re-"add" the option to fire all the correct filters. 
     485                add_option( $lock, $locked_at ); 
     486        } 
     487 
     488        $success = true; 
     489 
     490        reset( $revisions ); 
     491        do { 
     492                $this_revision = current( $revisions ); 
     493                $prev_revision = next( $revisions ); 
     494 
     495                $this_revision_version = _wp_get_post_revision_version( $this_revision ); 
     496 
     497                // Something terrible happened 
     498                if ( false === $this_revision_version ) 
     499                        continue; 
     500 
     501                // 1 is the latest revision version, so we're already up to date 
     502                if ( 0 < $this_revision_version ) 
     503                        continue; 
     504 
     505                // This revision is the oldest revision of the post. 
     506                // The correct post_author is probably $post->post_author, but that's only a good guess. 
     507                // Leave un-upgraded.  Will be caught by get_modified_post_author() on display. 
     508                if ( ! $prev_revision ) { 
     509                        continue; 
     510                } 
     511 
     512                $prev_revision_version = _wp_get_post_revision_version( $prev_revision ); 
     513 
     514                // If the previous revision is already up to date, it no longer has the information we need :( 
     515                if ( 0 < $prev_revision_version ) { 
     516                        continue; 
     517                } 
     518 
     519                // Upgrade this revision 
     520 
     521                // Cast as object so that wp_update_post() handles slashing for us 
     522                $update = (object) array( 
     523                        'ID'          => $this_revision->ID, 
     524                        'post_name'   => preg_replace( '/^(\d+)(?:-0)?-/', '\\1-1-', $this_revision->post_name ), 
     525                        'post_author' => $prev_revision->post_author, 
     526                ); 
     527 
     528                $result = wp_update_post( $update ); 
     529                if ( ! $result || is_wp_error( $result ) ) { 
     530                        // Wilhelm! 
     531                        $success = false; 
     532                        break; 
     533                } 
     534        } while ( $prev_revision ); 
     535 
     536        delete_option( $lock ); 
     537        return true; 
     538} 
     539 
     540 
    396541function _show_post_preview() { 
    397542 
    398543        if ( isset($_GET['preview_id']) && isset($_GET['preview_nonce']) ) { 
  • wp-includes/author-template.php

     
    6161/** 
    6262 * Retrieve the author who last edited the current post. 
    6363 * 
     64 * As of WordPress 3.6, returns the display name of the user who created the revision if called on a revision object. 
     65 * 
    6466 * @since 2.8 
    65  * @uses $post The current post's DB object. 
    6667 * @uses get_post_meta() Retrieves the ID of the author who last edited the current post. 
    6768 * @uses get_userdata() Retrieves the author's DB object. 
    6869 * @uses apply_filters() Calls 'the_modified_author' hook on the author display name. 
     70 * 
     71 * @param mixed $post_id Post ID, WP_Post, or falsey to use the current post. 
    6972 * @return string The author's display name. 
    7073 */ 
    71 function get_the_modified_author() { 
    72         if ( $last_id = get_post_meta( get_post()->ID, '_edit_last', true) ) { 
    73                 $last_user = get_userdata($last_id); 
    74                 return apply_filters('the_modified_author', $last_user->display_name); 
     74function get_the_modified_author( $post_id = 0 ) { 
     75        $post = get_post( $post_id ); 
     76        if ( ! $post ) 
     77                return; 
     78 
     79        $unknown = false; 
     80 
     81        if ( 'revision' === $post->post_type ) { 
     82                // _wp_get_post_revision_version() can return false 
     83                $revision_version = _wp_get_post_revision_version( $post ); 
     84                if ( false === $revision_version ) { 
     85                        // False means something horrible happened.  Just return something. 
     86                        $modified_author_id = $post->post_author; 
     87                } elseif ( 0 === $revision_version ) { 
     88                        // Set as fallback 
     89                        $modified_author_id = $post->post_author; 
     90 
     91                        $revisions = wp_get_post_revisions( $post->post_parent ); 
     92                        reset( $revisions ); 
     93                        do { 
     94                                $this_revision = current( $revisions ); 
     95                                $prev_revision = next( $revisions ); // Ordered DESC 
     96 
     97                                if ( $post->ID == $this_revision->ID && $prev_revision ) { 
     98                                        $prev_revision_version = _wp_get_post_revision_version( $prev_revision ); 
     99                                        if ( 0 === $prev_revision_version ) { 
     100                                                $modified_author_id = $prev_revision->post_author; 
     101                                        } else { 
     102                                                $unknown = true; 
     103                                        } 
     104                                        break; 
     105                                } 
     106                        } while ( $prev_revision ); 
     107                } else { 
     108                        // Everything is up to date 
     109                        $modified_author_id = $post->post_author; 
     110                } 
     111        } else { 
     112                $modified_author_id = get_post_meta( $post->ID, '_edit_last', true ); 
    75113        } 
     114 
     115        if ( ! $modified_author_id ) 
     116                return; 
     117 
     118        $modified_author = get_userdata( $modified_author_id ); 
     119 
     120        $display_name = $modified_author->display_name; 
     121        if ( $unknown ) { 
     122                $display_name = sprintf( _x( '%1$s?', 'Unknown revision author name: %1$s = display_name of best guess at author' ), $display_name ); 
     123        } 
     124 
     125        return apply_filters( 'the_modified_author', $display_name ); 
    76126} 
    77127 
    78128/** 
  • wp-admin/includes/ajax-actions.php

     
    22152215 
    22162216                if ( $compare_two_mode ) { 
    22172217                        $compare_to_gravatar = get_avatar( $left_revision->post_author, 24 ); 
    2218                         $compare_to_author = get_the_author_meta( 'display_name', $left_revision->post_author ); 
     2218                        $compare_to_author = get_the_modified_author( $left_revision->ID ); 
    22192219                        $compare_to_date = date_i18n( $datef, strtotime( $left_revision->post_modified ) ); 
    22202220 
    22212221                        $revision_from_date_author = sprintf( 
     
    22292229                } 
    22302230 
    22312231                $gravatar = get_avatar( $revision->post_author, 24 ); 
    2232                 $author = get_the_author_meta( 'display_name', $revision->post_author ); 
     2232                $author = $author = get_the_modified_author( $revision->ID ); 
    22332233                $date = date_i18n( $datef, strtotime( $revision->post_modified ) ); 
    22342234                $revision_date_author = sprintf( 
    22352235                        /* translators: post revision title: 1: author avatar, 2: author name, 3: time ago, 4: date */ 
  • wp-admin/includes/post.php

     
    249249 
    250250        add_meta( $post_ID ); 
    251251 
    252         update_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID ); 
    253  
    254252        wp_update_post( $post_data ); 
    255253 
    256254        // Now that we have an ID we can fix any attachment anchor hrefs 
     
    565563 
    566564        add_meta( $post_ID ); 
    567565 
    568         add_post_meta( $post_ID, '_edit_last', $GLOBALS['current_user']->ID ); 
    569  
    570566        // Now that we have an ID we can fix any attachment anchor hrefs 
    571567        _fix_attachment_links( $post_ID ); 
    572568 
  • wp-admin/js/revisions.js

     
    479479                                                ( REVAPP._right_diff >= REVAPP._revisions.length ) ? '' : REVAPP._revisions.at( REVAPP._right_diff ).get( 'revision_date_author_short' ) ); 
    480480                                } else { 
    481481                                        REVAPP.addTooltip ( $( 'a.ui-slider-handle' ), 
    482                                                 ( REVAPP._right_diff >= REVAPP._revisions.length ) ? '' : REVAPP._revisions.at( REVAPP._right_diff ).get( 'revision_date_author_short' ) ); 
     482                                                ( REVAPP._right_diff > REVAPP._revisions.length ) ? '' : REVAPP._revisions.at( REVAPP._right_diff - 1 ).get( 'revision_date_author_short' ) ); 
    483483                                } 
    484484 
    485485                                //