Make WordPress Core

Ticket #24425: 24425.3.diff

File 24425.3.diff, 16.4 KB (added by nacin, 12 years ago)
  • wp-includes/revision.php

     
    681681
    682682        return true;
    683683}
    684 
    685 /**
    686  * Displays a human readable HTML representation of the difference between two strings.
    687  * similar to wp_text_diff, but tracks and returns could of lines added and removed
    688  *
    689  * @since 3.6.0
    690  *
    691  * @see wp_parse_args() Used to change defaults to user defined settings.
    692  * @uses Text_Diff
    693  * @uses WP_Text_Diff_Renderer_Table
    694  *
    695  * @param string $left_string "old" (left) version of string
    696  * @param string $right_string "new" (right) version of string
    697  * @param string|array $args Optional. Change 'title', 'title_left', and 'title_right' defaults.
    698  * @return array contains html, linesadded & linesdeletd, empty string if strings are equivalent.
    699  */
    700 function wp_text_diff_with_count( $left_string, $right_string, $args = null ) {
    701         $defaults = array( 'title' => '', 'title_left' => '', 'title_right' => '' );
    702         $args = wp_parse_args( $args, $defaults );
    703 
    704         if ( ! class_exists( 'WP_Text_Diff_Renderer_Table' ) )
    705                         require( ABSPATH . WPINC . '/wp-diff.php' );
    706 
    707         $left_string  = normalize_whitespace( $left_string );
    708         $right_string = normalize_whitespace( $right_string );
    709 
    710         $left_lines  = explode( "\n", $left_string );
    711         $right_lines = explode( "\n", $right_string) ;
    712 
    713         $text_diff = new Text_Diff($left_lines, $right_lines  );
    714         $lines_added = $text_diff->countAddedLines();
    715         $lines_deleted = $text_diff->countDeletedLines();
    716 
    717         $renderer  = new WP_Text_Diff_Renderer_Table();
    718         $diff = $renderer->render( $text_diff );
    719 
    720         if ( !$diff )
    721                         return '';
    722 
    723                 $r  = "<table class='diff'>\n";
    724 
    725         if ( ! empty( $args[ 'show_split_view' ] ) ) {
    726                 $r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />";
    727         } else {
    728                 $r .= "<col class='content' />";
    729         }
    730 
    731         if ( $args['title'] || $args['title_left'] || $args['title_right'] )
    732                 $r .= "<thead>";
    733         if ( $args['title'] )
    734                 $r .= "<tr class='diff-title'><th colspan='4'>$args[title]</th></tr>\n";
    735         if ( $args['title_left'] || $args['title_right'] ) {
    736                 $r .= "<tr class='diff-sub-title'>\n";
    737                 $r .= "\t<td></td><th>$args[title_left]</th>\n";
    738                 $r .= "\t<td></td><th>$args[title_right]</th>\n";
    739                 $r .= "</tr>\n";
    740         }
    741         if ( $args['title'] || $args['title_left'] || $args['title_right'] )
    742                 $r .= "</thead>\n";
    743 
    744         $r .= "<tbody>\n$diff\n</tbody>\n";
    745         $r .= "</table>";
    746 
    747         return array( 'html' => $r, 'lines_added' => $lines_added, 'lines_deleted' => $lines_deleted );
    748 }
  • wp-admin/admin-ajax.php

     
    4242
    4343$core_actions_get = array(
    4444        'fetch-list', 'ajax-tag-search', 'wp-compression-test', 'imgedit-preview', 'oembed-cache',
    45         'autocomplete-user', 'dashboard-widgets', 'logged-in', 'revisions-data'
     45        'autocomplete-user', 'dashboard-widgets', 'logged-in',
    4646);
    4747
    4848$core_actions_post = array(
     
    5656        'save-widget', 'set-post-thumbnail', 'date_format', 'time_format', 'wp-fullscreen-save-post',
    5757        'wp-remove-post-lock', 'dismiss-wp-pointer', 'upload-attachment', 'get-attachment',
    5858        'query-attachments', 'save-attachment', 'save-attachment-compat', 'send-link-to-editor',
    59         'send-attachment-to-editor', 'save-attachment-order', 'heartbeat', 'show-post-format-ui',
     59        'send-attachment-to-editor', 'save-attachment-order', 'heartbeat', 'get-revision-diffs',
     60        'show-post-format-ui',
    6061);
    6162
    6263// Register core Ajax calls.
  • wp-admin/includes/ajax-actions.php

     
    21022102        wp_send_json($response);
    21032103}
    21042104
    2105 function wp_ajax_revisions_data() {
    2106         check_ajax_referer( 'revisions-ajax-nonce', 'nonce' );
     2105function wp_ajax_get_revision_diffs() {
     2106        require ABSPATH . 'wp-admin/includes/revision.php';
    21072107
    2108         $compare_to = ! empty( $_GET['compare_to'] ) ? absint( $_GET['compare_to'] ) : 0;
    2109         $show_autosaves = ! empty( $_GET['show_autosaves'] );
    2110         $show_split_view = ! empty( $_GET['show_split_view'] );
    2111         $post_id = ! empty( $_GET['post_id'] ) ? absint( $_GET['post_id'] ) : 0;
    2112         $right_handle_at = ! empty( $_GET['right_handle_at'] ) ? (int) $_GET['right_handle_at'] : 0;
    2113         $left_handle_at = ! empty( $_GET['left_handle_at'] ) ? (int) $_GET['left_handle_at'] : 0;
    2114         $single_revision_id = ! empty( $_GET['single_revision_id'] ) ? absint( $_GET['single_revision_id'] ) : 0;
    2115         $compare_two_mode = (bool) $post_id;
     2108        // check_ajax_referer( 'revisions-ajax-nonce', 'nonce' );
    21162109
    2117         $all_the_revisions = array();
    2118         if ( ! $post_id )
    2119                 $post_id = $compare_to;
     2110        if ( ! $post = get_post( (int) $_REQUEST['post_id'] ) )
     2111                wp_send_json_error();
    21202112
    2121         if ( ! current_user_can( 'read_post', $post_id ) )
    2122                 continue;
     2113        if ( ! current_user_can( 'read_post', $post->ID ) )
     2114                wp_send_json_error();
    21232115
    2124         if ( ! $revisions = wp_get_post_revisions( $post_id ) )
    2125                 return;
     2116        // Really just pre-loading the cache here.
     2117        if ( ! $revisions = wp_get_post_revisions( $post->ID ) )
     2118                wp_send_json_error();
    21262119
    2127         $left_revision = get_post( $compare_to );
     2120        $return = array();
     2121        @set_time_limit( count( $_REQUEST['compare'] ) );
    21282122
    2129         // single model fetch mode
    2130         // return the diff of a single revision comparison
    2131         if ( $single_revision_id ) {
    2132                 $right_revision = get_post( $single_revision_id );
     2123        foreach ( $_REQUEST['compare'] as $compare_key ) {
     2124                list( $compare_from, $compare_to ) = explode( ':', $compare_key ); // from:to
    21332125
    2134                 if ( ! $compare_to )
    2135                         $left_revision = get_post( $post_id );
     2126                $return[ $compare_key ] = wp_get_revision_ui_diff( $post, $compare_from, $compare_to );
     2127        }
    21362128
    2137                 // make sure the right revision is the most recent, except on oldest revision
    2138                 if ( $compare_to && $right_revision->post_date < $left_revision->post_date ) {
    2139                         $temp = $left_revision;
    2140                         $left_revision = $right_revision;
    2141                         $right_revision = $temp;
    2142                 }
    2143 
    2144                 $lines_added = $lines_deleted = 0;
    2145                 $content = '';
    2146                 // compare from left to right, passed from application
    2147                 foreach ( _wp_post_revision_fields() as $field => $field_value ) {
    2148                         $left_content = apply_filters( "_wp_post_revision_field_$field", $left_revision->$field, $field, $left_revision, 'left' );
    2149                         $right_content = apply_filters( "_wp_post_revision_field_$field", $right_revision->$field, $field, $right_revision, 'right' );
    2150 
    2151                         add_filter( "_wp_post_revision_field_$field", 'htmlspecialchars' );
    2152 
    2153                         $args = array();
    2154 
    2155                         if ( $show_split_view )
    2156                                  $args = array( 'show_split_view' => true );
    2157 
    2158                         // compare_to == 0 means first revision, so compare to a blank field to show whats changed
    2159                         $diff = wp_text_diff_with_count( ( 0 == $compare_to ) ? '' : $left_content, $right_content, $args );
    2160 
    2161                         if ( isset( $diff[ 'html' ] ) ) {
    2162                                 $content .= sprintf( '<div class="diff-label">%s</div>', $field_value );
    2163                                 $content .= $diff[ 'html' ];
    2164                         }
    2165 
    2166                         if ( isset( $diff[ 'lines_added' ] ) )
    2167                                 $lines_added = $lines_added + $diff[ 'lines_added' ];
    2168 
    2169                         if ( isset( $diff[ 'lines_deleted' ] ) )
    2170                                 $lines_deleted = $lines_deleted + $diff[ 'lines_deleted' ];
    2171                 }
    2172                 $content = '' == $content ? __( 'No difference' ) : $content;
    2173 
    2174                 $all_the_revisions = array (
    2175                         'diff'         => $content,
    2176                         'linesDeleted' => $lines_deleted,
    2177                         'linesAdded'   => $lines_added
    2178                 );
    2179 
    2180                 echo json_encode( $all_the_revisions );
    2181                 exit();
    2182         } // end single model fetch
    2183 
    2184         $count = -1;
    2185 
    2186         // reverse the list to start with oldest revision
    2187         $revisions = array_reverse( $revisions );
    2188 
    2189         $previous_revision_id = 0;
    2190 
    2191         /* translators: revision date format, see http://php.net/date */
    2192         $datef = _x( 'j F, Y @ G:i:s', 'revision date format');
    2193 
    2194         foreach ( $revisions as $revision ) :
    2195                 if ( ! $show_autosaves && wp_is_post_autosave( $revision ) )
    2196                         continue;
    2197 
    2198                 $revision_from_date_author = '';
    2199                 $is_current_revision = false;
    2200                 $count++;
    2201 
    2202                 /**
    2203                 * return blank data for diffs to the left of the left handle (for right handel model)
    2204                 * or to the right of the right handle (for left handel model)
    2205                 * and visa versa in RTL mode
    2206                 */
    2207                 if( ! is_rtl() ) {
    2208                         if ( ( ( 0 != $left_handle_at && $count < $left_handle_at ) ||
    2209                                  ( 0 != $right_handle_at && $count > ( $right_handle_at - 2 ) ) ) ) {
    2210                                 $all_the_revisions[] = array (
    2211                                         'ID' => $revision->ID,
    2212                                 );
    2213                                 continue;
    2214                         }
    2215                 } else { // is_rtl
    2216                         if ( ( 0 != $left_handle_at && $count > ( $left_handle_at - 1 ) ||
    2217                                  ( 0 != $left_handle_at && $count < $right_handle_at ) ) ) {
    2218                                 $all_the_revisions[] = array (
    2219                                         'ID' => $revision->ID,
    2220                                 );
    2221                                 continue;
    2222                         }
    2223                 }
    2224 
    2225                 if ( $compare_two_mode ) {
    2226                         $compare_to_gravatar = get_avatar( $left_revision->post_author, 24 );
    2227                         $compare_to_author = get_the_author_meta( 'display_name', $left_revision->post_author );
    2228                         $compare_to_date = date_i18n( $datef, strtotime( $left_revision->post_modified ) );
    2229 
    2230                         $revision_from_date_author = sprintf(
    2231                                 /* translators: post revision title: 1: author avatar, 2: author name, 3: time ago, 4: date */
    2232                                 _x( '%1$s %2$s, %3$s ago (%4$s)', 'post revision title' ),
    2233                                 $compare_to_gravatar,
    2234                                 $compare_to_author,
    2235                                 human_time_diff( strtotime( $left_revision->post_modified ), current_time( 'timestamp' ) ),
    2236                                 $compare_to_date
    2237                         );
    2238                 }
    2239 
    2240                 $gravatar = get_avatar( $revision->post_author, 24 );
    2241                 $author = get_the_author_meta( 'display_name', $revision->post_author );
    2242                 $date = date_i18n( $datef, strtotime( $revision->post_modified ) );
    2243                 $revision_date_author = sprintf(
    2244                         /* translators: post revision title: 1: author avatar, 2: author name, 3: time ago, 4: date */
    2245                         _x( '%1$s %2$s, %3$s ago (%4$s)', 'post revision title' ),
    2246                         $gravatar,
    2247                         $author,
    2248                         human_time_diff( strtotime( $revision->post_modified ), current_time( 'timestamp' ) ),
    2249                         $date
    2250                 );
    2251 
    2252                 /* translators: 1: date */
    2253                 $autosavef = _x( '%1$s [Autosave]', 'post revision title extra' );
    2254                 /* translators: 1: date */
    2255                 $currentf  = _x( '%1$s [Current Revision]', 'post revision title extra' );
    2256 
    2257                 if ( ! $post = get_post( $post_id ) )
    2258                         continue;
    2259 
    2260                 if ( $left_revision->post_modified === $post->post_modified )
    2261                         $revision_from_date_author = sprintf( $currentf, $revision_from_date_author );
    2262                 elseif ( wp_is_post_autosave( $left_revision ) )
    2263                         $revision_from_date_author = sprintf( $autosavef, $revision_from_date_author );
    2264 
    2265                 if ( $revision->post_modified === $post->post_modified ) {
    2266                         $revision_date_author = sprintf( $currentf, $revision_date_author );
    2267                         $is_current_revision = true;
    2268                 } elseif ( wp_is_post_autosave( $revision ) ) {
    2269                         $revision_date_author = sprintf( $autosavef, $revision_date_author );
    2270                 }
    2271 
    2272                 /* translators: revision date short format, see http://php.net/date */
    2273                 $date_short_format = _x( 'j M @ G:i', 'revision date short format');
    2274                 $date_short = date_i18n( $date_short_format, strtotime( $revision->post_modified ) );
    2275 
    2276                 $revision_date_author_short = sprintf(
    2277                         '%s <strong>%s</strong><br />%s',
    2278                         $gravatar,
    2279                         $author,
    2280                         $date_short
    2281                 );
    2282 
    2283                 $restore_link = wp_nonce_url(
    2284                         add_query_arg(
    2285                                 array( 'revision' => $revision->ID,
    2286                                         'action' => 'restore' ),
    2287                                         admin_url( 'revision.php' )
    2288                         ),
    2289                         "restore-post_{$revision->ID}"
    2290                 );
    2291 
    2292                 // if this is a left handled calculation swap data
    2293                 if ( 0 != $right_handle_at ) {
    2294                         $tmp = $revision_from_date_author;
    2295                         $revision_from_date_author = $revision_date_author;
    2296                         $revision_date_author = $tmp;
    2297                 }
    2298 
    2299                 if ( ( $compare_two_mode || -1 !== $previous_revision_id ) ) {
    2300                         $all_the_revisions[] = array (
    2301                                 'ID'           => $revision->ID,
    2302                                 'titleTo'      => $revision_date_author,
    2303                                 'titleFrom'    => $revision_from_date_author,
    2304                                 'titleTooltip' => $revision_date_author_short,
    2305                                 'restoreLink'  => urldecode( $restore_link ),
    2306                                 'previousID'   => $previous_revision_id,
    2307                                 'isCurrent'    => $is_current_revision,
    2308                         );
    2309                 }
    2310                 $previous_revision_id = $revision->ID;
    2311 
    2312         endforeach;
    2313 
    2314         // in RTL + single handle mode, reverse the revision direction
    2315         if ( is_rtl() && $compare_two_mode )
    2316                 $all_the_revisions = array_reverse( $all_the_revisions );
    2317 
    2318         echo json_encode( $all_the_revisions );
    2319         exit();
     2129        wp_send_json_success( $return );
    23202130}
  • wp-admin/includes/revision.php

     
     1<?php
     2
     3function wp_get_revision_ui_diff( $post, $compare_from, $compare_to ) {
     4        if ( ! $post = get_post( $post ) )
     5                return false;
     6
     7        if ( $compare_from ) {
     8                if ( ! $compare_from = get_post( $compare_from ) )
     9                        return false;
     10        } else {
     11                // If we're dealing with the first revision...
     12                $compare_from = false;
     13        }
     14
     15        if ( ! $compare_to = get_post( $compare_to ) )
     16                return false;
     17
     18        // If comparing revisions, make sure we're dealing with the right post parent.
     19        if ( $compare_from && $compare_from->post_parent !== $post->ID )
     20                return false;
     21        if ( $compare_to->post_parent !== $post->ID )
     22                return false;
     23
     24        if ( $compare_from && strtotime( $compare_from->post_date_gmt ) > strtotime( $compare_to->post_date_gmt ) ) {
     25                $temp = $compare_from;
     26                $compare_from = $compare_to;
     27                $compare_to = $temp;
     28        }
     29
     30        $return = array();
     31
     32        foreach ( _wp_post_revision_fields() as $field => $name ) {
     33                $content_from = $compare_from ? apply_filters( "_wp_post_revision_field_$field", $compare_from->$field, $field, $compare_from, 'left' ) : '';
     34                $content_to = apply_filters( "_wp_post_revision_field_$field", $compare_to->$field, $field, $compare_to, 'right' );
     35
     36                add_filter( "_wp_post_revision_field_$field", 'esc_html' );
     37
     38                // compare_to == 0 means first revision, so compare to a blank field to show whats changed
     39                $diff = wp_text_diff( $content_from, $content_to, array( 'show_split_view' => true ) );
     40
     41                if ( ! $diff && 'post_title' === $field ) {
     42                        // It's a better user experience to still show the Title, even if it didn't change.
     43                        // No, you didn't see this.
     44                        $diff = "<table class='diff'><col class='ltype' /><col class='content' /><col class='ltype' /><col class='content' /><tbody><tr>";
     45                        $diff .= '<td>' . esc_html( $compare_from->post_title ) . '</td><td></td><td>' . esc_html( $compare_to->post_title ) . '</td>';
     46                        $diff .= '</tr></tbody>';
     47                        $diff .= '</table>';
     48                }
     49
     50                if ( $diff )
     51                        $return[ $field ] = compact( 'name', 'diff' );
     52        }
     53        return $return;
     54}
     55
     56function wp_prepare_revisions_for_js( $post ) {
     57        $post = get_post( $post );
     58        $revisions = array();
     59        $current = current_time( 'timestamp' );
     60
     61        $revisions = wp_get_post_revisions( $post->ID );
     62
     63        cache_users( wp_list_pluck( $revisions, 'post_author' ) );
     64
     65        foreach ( $revisions as $revision ) {
     66                $modified_gmt = strtotime( $revision->post_modified_gmt );
     67                $revisions[ $revision->ID ] = array(
     68                        'revisionID' => $revision->ID,
     69                        'timeAgo' => human_time_diff( $modified_gmt, $current ),
     70                        'avatar' => get_avatar( $revision->post_author, 24 ),
     71                        'authorId' => (int) $revision->post_author,
     72                        'authorName' => get_the_author_meta( 'display_name', $revision->post_author ),
     73                        'title' => get_the_title( $post->ID ),
     74                        'date' => date_i18n( __( 'M j, Y @ G:i' ), $modified_gmt ),
     75                        'dateShort' => date_i18n( _x( 'j M @ G:i', 'revision date short format' ), $modified_gmt ),
     76                        'autosave' => wp_is_post_autosave( $revision ),
     77                        'current' => $revision->post_modified_gmt === $post->post_modified_gmt,
     78                        'restoreNonce' => wp_create_nonce( 'restore-post_' . $revision->ID ),
     79                );
     80        }
     81
     82        $settings = array(
     83                'restoreUrl' => admin_url( 'revision.php?action=restore' ) // &revision=$ID&_wpnonce=$restoreNonce
     84        );
     85
     86        return compact( 'revisions', 'settings' );
     87}
  • wp-admin/revision.php

     
    88
    99/** WordPress Administration Bootstrap */
    1010require_once('./admin.php');
     11
     12require ABSPATH . 'wp-admin/includes/revision.php';
     13
     14// wp_get_revision_ui_diff( $post, $compare_from, $compare_to )
     15// wp_prepare_revisions_for_js( $post )
     16
    1117wp_reset_vars( array( 'revision', 'action' ) );
    1218
    1319$revision_id = absint( $revision );
     
    4450        if ( ! $post = get_post( $revision->post_parent ) )
    4551                break;
    4652
     53        var_dump( wp_prepare_revisions_for_js( $post ) );
     54
    4755        if ( ! current_user_can( 'read_post', $revision->ID ) || ! current_user_can( 'read_post', $post->ID ) )
    4856                break;
    4957