Ticket #6775: 6775.diff
| File 6775.diff, 91.2 kB (added by mdawaffe, 8 months ago) |
|---|
-
wp-includes/default-filters.php
old new 178 178 add_action('init', 'smilies_init', 5); 179 179 add_action( 'plugins_loaded', 'wp_maybe_load_widgets', 0 ); 180 180 add_action( 'shutdown', 'wp_ob_end_flush_all', 1); 181 add_action( 'pre_post_update', 'wp_save_revision' ); 181 182 add_action('publish_post', '_publish_post_hook', 5, 1); 182 183 add_action('future_post', '_future_post_hook', 5, 2); 183 184 add_action('future_page', '_future_post_hook', 5, 2); -
wp-includes/post-template.php
old new 564 564 return false; 565 565 } 566 566 567 ?> 567 /** 568 * wp_post_revision_time() - returns formatted datetimestamp of a revision 569 * 570 * @package WordPress 571 * @subpackage Post Revisions 572 * @since 2.6 573 * 574 * @uses wp_get_revision() 575 * @uses date_i18n() 576 * 577 * @param int|object $revision revision ID or revision object 578 * @return string i18n formatted datetimestamp or localized 'Corrent Revision' 579 */ 580 function wp_post_revision_time( $revision ) { 581 if ( !$revision = wp_get_revision( $revision ) ) { 582 if ( $revision = get_post( $revision ) ) 583 return __( 'Current Revision' ); 584 return $revision; 585 } 586 587 $datef = _c( 'j F, Y @ G:i|revision date format'); 588 return date_i18n( $datef, strtotime( $revision->post_date_gmt . ' +0000' ) ); 589 } 590 591 /** 592 * wp_list_post_revisions() - echoes list of a post's revisions 593 * 594 * Can output either a UL with edit links or a TABLE with diff interface, and restore action links 595 * 596 * Second argument controls parameters: 597 * (bool) parent : include the parent (the "Current Revision") in the list 598 * (string) format : 'list' or 'form-table'. 'list' outputs UL, 'form-table' outputs TABLE with UI 599 * (int) right : what revision is currently being viewed - used in form-table format 600 * (int) left : what revision is currently being diffed against right - used in form-table format 601 * 602 * @package WordPress 603 * @subpackage Post Revisions 604 * @since 2.6 605 * 606 * @uses wp_get_post_revisions() 607 * @uses wp_post_revision_time() 608 * @uses get_edit_post_link() 609 * @uses get_author_name() 610 * 611 * @param int|object $post_id post ID or post object 612 * @param string|array $args see description @see wp_parse_args() 613 */ 614 function wp_list_post_revisions( $post_id = 0, $args = null ) { // TODO? split into two functions (list, form-table) ? 615 if ( !$post = get_post( $post_id ) ) 616 return; 617 618 if ( !$revisions = wp_get_post_revisions( $post->ID ) ) 619 return; 620 621 $defaults = array( 'parent' => false, 'right' => false, 'left' => false, 'format' => 'list' ); 622 extract( wp_parse_args( $args, $defaults ), EXTR_SKIP ); 623 624 $titlef = _c( '%1$s by %2$s|post revision 1:datetime, 2:name' ); 625 626 if ( $parent ) 627 array_unshift( $revisions, $post ); 628 629 $rows = ''; 630 $class = false; 631 foreach ( $revisions as $revision ) { 632 $date = wp_post_revision_time( $revision ); 633 if ( $link = get_edit_post_link( $revision->ID ) ) 634 $date = "<a href='$link'>$date</a>"; 635 $name = get_author_name( $revision->post_author ); 636 637 if ( 'form-table' == $format ) { 638 if ( $left ) 639 $old_checked = $left == $revision->ID ? ' checked="checked"' : ''; 640 else 641 $old_checked = $new_checked ? ' checked="checked"' : ''; 642 $new_checked = $right == $revision->ID ? ' checked="checked"' : ''; 643 644 $class = $class ? '' : " class='alternate'"; 645 646 if ( $post->ID != $revision->ID && current_user_can( 'edit_post', $post->ID ) ) 647 $actions = '<a href="' . wp_nonce_url( add_query_arg( array( 'revision' => $revision->ID, 'diff' => false, 'restore' => 'restore' ) ), "restore-post_$post->ID|$revision->ID" ) . '">' . __( 'Restore' ) . '</a>'; 648 else 649 $actions = ''; 650 651 $rows .= "<tr$class>\n"; 652 $rows .= "\t<th style='white-space: nowrap' scope='row'><input type='radio' name='diff' value='$revision->ID'$old_checked /><input type='radio' name='revision' value='$revision->ID'$new_checked />\n"; 653 $rows .= "\t<td>$date</td>\n"; 654 $rows .= "\t<td>$name</td>\n"; 655 $rows .= "\t<td class='action-links'>$actions</td>\n"; 656 $rows .= "</tr>\n"; 657 } else { 658 $rows .= "\t<li>" . sprintf( $titlef, $date, $name ). "</li>\n"; 659 } 660 } 661 662 if ( 'form-table' == $format ) : ?> 663 664 <form action="revision.php" method="get"> 665 666 <div class="tablenav"> 667 <div class="alignleft"> 668 <input type="submit" class="button-secondary" value="<?php _e( 'Compare Revisions' ); ?>" /> 669 </div> 670 </div> 671 672 <br class="clear" /> 673 674 <table class="widefat post-revisions"> 675 <col /> 676 <col style="width: 33%" /> 677 <col style="width: 33%" /> 678 <col style="width: 33%" /> 679 <thead> 680 <th scope="col"></th> 681 <th scope="col"><?php _e( 'Date Created' ); ?></th> 682 <th scope="col"><?php _e( 'Author' ); ?></th> 683 <th scope="col" class="action-links"><?php _e( 'Actions' ); ?></th> 684 </thead> 685 <tbody> 686 687 <?php echo $rows; ?> 688 689 </tbody> 690 </table> 691 692 <?php 693 else : 694 echo "<ul class='post-revisions'>\n"; 695 echo $rows; 696 echo "</ul>"; 697 endif; 698 699 } -
wp-includes/post.php
old new 2990 2990 } 2991 2991 } 2992 2992 2993 /* Post Revisions */ 2994 2995 /** 2996 * _wp_revision_fields() - determines which fields of posts are to be saved in revisions 2997 * 2998 * Does two things. If passed a postn *array*, it will return a post array ready to be 2999 * insterted into the posts table as a post revision. 3000 * Otherwise, returns an array whose keys are the post fields to be saved post revisions. 3001 * 3002 * @package WordPress 3003 * @subpackage Post Revisions 3004 * @since 2.6 3005 * 3006 * @param array $post optional a post array to be processed for insertion as a post revision 3007 * @return array post array ready to be inserted as a post revision or array of fields that can be versioned 3008 */ 3009 function _wp_revision_fields( $post = null ) { 3010 static $fields = false; 3011 3012 if ( !$fields ) { 3013 // Allow these to be versioned 3014 $fields = array( 3015 'post_title' => __( 'Title' ), 3016 'post_author' => __( 'Author' ), 3017 'post_content' => __( 'Content' ), 3018 'post_excerpt' => __( 'Excerpt' ), 3019 ); 3020 3021 // WP uses these internally either in versioning or elsewhere - they cannot be versioned 3022 foreach ( array( 'ID', 'post_name', 'post_parent', 'post_date', 'post_date_gmt', 'post_status', 'post_type', 'comment_count' ) as $protect ) 3023 unset( $fields[$protect] ); 3024 } 3025 3026 if ( !is_array($post) ) 3027 return $fields; 3028 3029 $return = array(); 3030 foreach ( array_intersect( array_keys( $post ), array_keys( $fields ) ) as $field ) 3031 $return[$field] = $post[$field]; 3032 3033 $return['post_parent'] = $post['ID']; 3034 $return['post_status'] = 'inherit'; 3035 $return['post_type'] = 'revision'; 3036 $return['post_name'] = "$post[ID]-revision"; 3037 $return['post_date'] = $post['post_modified']; 3038 $return['post_date_gmt'] = $post['post_modified_gmt']; 3039 3040 return $return; 3041 } 3042 3043 /** 3044 * wp_save_revision() - Saves an already existing post as a post revision. Typically used immediately prior to post updates. 3045 * 3046 * @package WordPress 3047 * @subpackage Post Revisions 3048 * @since 2.6 3049 * 3050 * @uses _wp_put_revision() 3051 * 3052 * @param int $post_id The ID of the post to save as a revision 3053 * @return mixed null or 0 if error, new revision ID if success 3054 */ 3055 function wp_save_revision( $post_id ) { 3056 // TODO: rework autosave to use special type of post revision 3057 if ( @constant( 'DOING_AUTOSAVE' ) ) 3058 return; 3059 3060 if ( !$post = get_post( $post_id, ARRAY_A ) ) 3061 return; 3062 3063 // TODO: open this up for pages also 3064 if ( 'post' != $post->post_type ) 3065 retun; 3066 3067 return _wp_put_revision( $post ); 3068 } 3069 3070 /** 3071 * _wp_put_revision() - Inserts post data into the posts table as a post revision 3072 * 3073 * @package WordPress 3074 * @subpackage Post Revisions 3075 * @since 2.6 3076 * 3077 * @uses wp_insert_post() 3078 * 3079 * @param int|object|array $post post ID, post object OR post array 3080 * @return mixed null or 0 if error, new revision ID if success 3081 */ 3082 function _wp_put_revision( $post = null ) { 3083 if ( is_object($post) ) 3084 $post = get_object_vars( $post ); 3085 elseif ( !is_array($post) ) 3086 $post = get_post($post, ARRAY_A); 3087 3088 if ( !$post || empty($post['ID']) ) 3089 return; 3090 3091 if ( isset($post['post_type']) && 'revision' == $post_post['type'] ) 3092 return new WP_Error( 'post_type', __( 'Cannot create a revision of a revision' ) ); 3093 3094 $post = _wp_revision_fields( $post ); 3095 3096 if ( $revision_id = wp_insert_post( $post ) ) 3097 do_action( '_wp_put_revision', $revision_id ); 3098 3099 return $revision_id; 3100 } 3101 3102 /** 3103 * wp_get_revision() - Gets a post revision 3104 * 3105 * @package WordPress 3106 * @subpackage Post Revisions 3107 * @since 2.6 3108 * 3109 * @uses get_post() 3110 * 3111 * @param int|object $post post ID or post object 3112 * @param $output optional OBJECT, ARRAY_A, or ARRAY_N 3113 * @param string $filter optional sanitation filter. @see sanitize_post() 3114 * @return mixed null if error or post object if success 3115 */ 3116 function &wp_get_revision(&$post, $output = OBJECT, $filter = 'raw') { 3117 $null = null; 3118 if ( !$revision = get_post( $post, OBJECT, $filter ) ) 3119 return $revision; 3120 if ( 'revision' !== $revision->post_type ) 3121 return $null; 3122 3123 if ( $output == OBJECT ) { 3124 return $revision; 3125 } elseif ( $output == ARRAY_A ) { 3126 $_revision = get_object_vars($revision); 3127 return $_revision; 3128 } elseif ( $output == ARRAY_N ) { 3129 $_revision = array_values(get_object_vars($revision)); 3130 return $_revision; 3131 } 3132 3133 return $revision; 3134 } 3135 3136 /** 3137 * wp_restore_revision() - Restores a post to the specified revision 3138 * 3139 * Can restore a past using all fields of the post revision, or only selected fields. 3140 * 3141 * @package WordPress 3142 * @subpackage Post Revisions 3143 * @since 2.6 3144 * 3145 * @uses wp_get_revision() 3146 * @uses wp_update_post() 3147 * 3148 * @param int|object $revision_id revision ID or revision object 3149 * @param array $fields optional What fields to restore from. Defaults to all. 3150 * @return mixed null if error, false if no fields to restore, (int) post ID if success 3151 */ 3152 function wp_restore_revision( $revision_id, $fields = null ) { 3153 if ( !$revision = wp_get_revision( $revision_id, ARRAY_A ) ) 3154 return $revision; 3155 3156 if ( !is_array( $fields ) ) 3157 $fields = array_keys( _wp_revision_fields() ); 3158 3159 $update = array(); 3160 foreach( array_intersect( array_keys( $revision ), $fields ) as $field ) 3161 $update[$field] = $revision[$field]; 3162 3163 if ( !$update ) 3164 return false; 3165 3166 $update['ID'] = $revision['post_parent']; 3167 3168 if ( $post_id = wp_update_post( $update ) ) 3169 do_action( 'wp_restore_revision', $post_id, $revision['ID'] ); 3170 3171 return $post_id; 3172 } 3173 3174 /** 3175 * wp_delete_revision() - Deletes a revision. 3176 * 3177 * Deletes the row from the posts table corresponding to the specified revision 3178 * 3179 * @package WordPress 3180 * @subpackage Post Revisions 3181 * @since 2.6 3182 * 3183 * @uses wp_get_revision() 3184 * @uses wp_delete_post() 3185 * 3186 * @param int|object $revision_id revision ID or revision object 3187 * @param array $fields optional What fields to restore from. Defaults to all. 3188 * @return mixed null if error, false if no fields to restore, (int) post ID if success 3189 */ 3190 function wp_delete_revision( $revision_id ) { 3191 if ( !$revision = wp_get_revision( $revision_id ) ) 3192 return $revision; 3193 3194 if ( $delete = wp_delete_post( $revision->ID ) ) 3195 do_action( 'wp_delete_revision', $revision->ID, $revision ); 3196 3197 return $delete; 3198 } 3199 3200 /** 3201 * wp_get_post_revisions() - Returns all revisions of specified post 3202 * 3203 * @package WordPress 3204 * @subpackage Post Revisions 3205 * @since 2.6 3206 * 3207 * @uses get_children() 3208 * 3209 * @param int|object $post_id post ID or post object 3210 * @return array empty if no revisions 3211 */ 3212 function wp_get_post_revisions( $post_id = 0 ) { 3213 if ( ( !$post = get_post( $post_id ) ) || empty( $post->ID ) ) 3214 return array(); 3215 3216 if ( !$revisions = get_children( array( 'post_parent' => $post->ID, 'post_type' => 'revision' ) ) ) 3217 return array(); 3218 return $revisions; 3219 } 3220 2993 3221 ?> -
wp-includes/wp-diff.php
old new 1 <?php 2 3 if ( !class_exists( 'Text_Diff' ) ) { 4 require( 'Text/Diff.php' ); 5 require( 'Text/Diff/Renderer.php' ); 6 require( 'Text/Diff/Renderer/inline.php' ); 7 } 8 9 10 /* Descendent of a bastard child of piece of an old MediaWiki Diff Formatter 11 * 12 * Basically all that remains is the table structure and some method names. 13 */ 14 15 class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer { 16 var $_leading_context_lines = 10000; 17 var $_trailing_context_lines = 10000; 18 var $_diff_threshold = 0.6; 19 20 var $inline_diff_renderer = 'WP_Text_Diff_Renderer_inline'; 21 22 function Text_Diff_Renderer_Table( $params = array() ) { 23 $parent = get_parent_class($this); 24 $this->$parent( $params ); 25 } 26 27 function _startBlock( $header ) { 28 return ''; 29 } 30 31 function _lines( $lines, $prefix=' ' ) { 32 } 33 34 // HTML-escape parameter before calling this 35 function addedLine( $line ) { 36 return "<td>+</td><td class='diff-addedline'>{$line}</td>"; 37 } 38 39 // HTML-escape parameter before calling this 40 function deletedLine( $line ) { 41 return "<td>-</td><td class='diff-deletedline'>{$line}</td>"; 42 } 43 44 // HTML-escape parameter before calling this 45 function contextLine( $line ) { 46 return "<td> </td><td class='diff-context'>{$line}</td>"; 47 } 48 49 function emptyLine() { 50 return '<td colspan="2"> </td>'; 51 } 52 53 function _added( $lines, $encode = true ) { 54 $r = ''; 55 foreach ($lines as $line) { 56 if ( $encode ) 57 $line = htmlspecialchars( $line ); 58 $r .= '<tr>' . $this->emptyLine() . $this->addedLine( $line ) . "</tr>\n"; 59 } 60 return $r; 61 } 62 63 function _deleted( $lines, $encode = true ) { 64 $r = ''; 65 foreach ($lines as $line) { 66 if ( $encode ) 67 $line = htmlspecialchars( $line ); 68 $r .= '<tr>' . $this->deletedLine( $line ) . $this->emptyLine() . "</tr>\n"; 69 } 70 return $r; 71 } 72 73 function _context( $lines, $encode = true ) { 74 $r = ''; 75 foreach ($lines as $line) { 76 if ( $encode ) 77 $line = htmlspecialchars( $line ); 78 $r .= '<tr>' . 79 $this->contextLine( $line ) . $this->contextLine( $line ) . "</tr>\n"; 80 } 81 return $r; 82 } 83 84 // Process changed lines to do word-by-word diffs for extra highlighting (TRAC style) 85 // sometimes these lines can actually be deleted or added rows - we do additional processing 86 // to figure that out 87 function _changed( $orig, $final ) { 88 $r = ''; 89 90 // Does the aforementioned additional processing 91 // *_matches tell what rows are "the same" in orig and final. Those pairs will be diffed to get word changes 92 // match is numeric: an index in other column 93 // match is 'X': no match. It is a new row 94 // *_rows are column vectors for the orig column and the final column. 95 // row >= 0: an indix of the $orig or $final array 96 // row < 0: a blank row for that column 97 list($orig_matches, $final_matches, $orig_rows, $final_rows) = $this->interleave_changed_lines( $orig, $final ); 98 99 100 // These will hold the word changes as determined by an inline diff 101 $orig_diffs = array(); 102 $final_diffs = array(); 103 104 // Compute word diffs for each matched pair using the inline diff 105 foreach ( $orig_matches as $o => $f ) { 106 if ( is_numeric($o) && is_numeric($f) ) { 107 $text_diff = new Text_Diff( 'auto', array( array($orig[$o]), array($final[$f]) ) ); 108 $renderer = new $this->inline_diff_renderer; 109 $diff = $renderer->render( $text_diff ); 110 111 // If they're too different, don't include any <ins> or <dels> 112 if ( $diff_count = preg_match_all( '!(<ins>.*?</ins>|<del>.*?</del>)!', $diff, $diff_matches ) ) { 113 // length of all text between <ins> or <del> 114 $stripped_matches = strlen(strip_tags( join(' ', $diff_matches[0]) )); 115 // since we count lengith of text between <ins> or <del> (instead of picking just one), 116 // we double the length of chars not in those tags. 117 $stripped_diff = strlen(strip_tags( $diff )) * 2 - $stripped_matches; 118 $diff_ratio = $stripped_matches / $stripped_diff; 119 if ( $diff_ratio > $this->_diff_threshold ) 120 continue; // Too different. Don't save diffs. 121 } 122 123 // Un-inline the diffs by removing del or ins 124 $orig_diffs[$o] = preg_replace( '|<ins>.*?</ins>|', '', $diff ); 125 $final_diffs[$f] = preg_replace( '|<del>.*?</del>|', '', $diff ); 126 } 127 } 128 129 foreach ( array_keys($orig_rows) as $row ) { 130 // Both columns have blanks. Ignore them. 131 if ( $orig_rows[$row] < 0 && $final_rows[$row] < 0 ) 132 continue; 133 134 // If we have a word based diff, use it. Otherwise, use the normal line. 135 $orig_line = isset($orig_diffs[$orig_rows[$row]]) 136 ? $orig_diffs[$orig_rows[$row]] 137 : htmlspecialchars($orig[$orig_rows[$row]]); 138 $final_line = isset($final_diffs[$final_rows[$row]]) 139 ? $final_diffs[$final_rows[$row]] 140 : htmlspecialchars($final[$final_rows[$row]]); 141 142 if ( $orig_rows[$row] < 0 ) { // Orig is blank. This is really an added row. 143 $r .= $this->_added( array($final_line), false ); 144 } elseif ( $final_rows[$row] < 0 ) { // Final is blank. This is really a deleted row. 145 $r .= $this->_deleted( array($orig_line), false ); 146 } else { // A true changed row. 147 $r .= '<tr>' . $this->deletedLine( $orig_line ) . $this->addedLine( $final_line ) . "</tr>\n"; 148 } 149 } 150 151 return $r; 152 } 153 154 // Takes changed blocks and matches which rows in orig turned into which rows in final. 155 // Returns 156 // *_matches ( which rows match with which ) 157 // *_rows ( order of rows in each column interleaved with blank rows as necessary ) 158 function interleave_changed_lines( $orig, $final ) { 159 160 // Contains all pairwise string comparisons. Keys are such that this need only be a one dimensional array. 161 $matches = array(); 162 foreach ( array_keys($orig) as $o ) { 163 foreach ( array_keys($final) as $f ) { 164 $matches["$o,$f"] = $this->compute_string_distance( $orig[$o], $final[$f] ); 165 } 166 } 167 asort($matches); // Order by string distance. 168 169 $orig_matches = array(); 170 $final_matches = array(); 171 172 foreach ( $matches as $keys => $difference ) { 173 list($o, $f) = explode(',', $keys); 174 $o = (int) $o; 175 $f = (int) $f; 176 177 // Already have better matches for these guys 178 if ( isset($orig_matches[$o]) && isset($final_matches[$f]) ) 179 continue; 180 181 // First match for these guys. Must be best match 182 if ( !isset($orig_matches[$o]) && !isset($final_matches[$f]) ) { 183 $orig_matches[$o] = $f; 184 $final_matches[$f] = $o; 185 continue; 186 } 187 188 // Best match of this final is already taken? Must mean this final is a new row. 189 if ( isset($orig_matches[$o]) ) 190 $final_matches[$f] = 'x'; 191 192 // Best match of this orig is already taken? Must mean this orig is a deleted row. 193 elseif ( isset($final_matches[$f]) ) 194 $orig_matches[$o] = 'x'; 195 } 196 197 // We read the text in this order 198 ksort($orig_matches); 199 ksort($final_matches); 200 201 202 // Stores rows and blanks for each column. 203 $orig_rows = $orig_rows_copy = array_keys($orig_matches); 204 $final_rows = array_keys($final_matches); 205 206 // Interleaves rows with blanks to keep matches aligned. 207 // We may end up with some extraneous blank rows, but we'll just ignore them later. 208 foreach ( $orig_rows_copy as $orig_row ) { 209 $final_pos = array_search($orig_matches[$orig_row], $final_rows, true); 210 $orig_pos = (int) array_search($orig_row, $orig_rows, true); 211 212 if ( false === $final_pos ) { // This orig is paired with a blank final. 213 array_splice( $final_rows, $orig_pos, 0, -1 ); 214 } elseif ( $final_pos < $orig_pos ) { // This orig's match is up a ways. Pad final with blank rows. 215 $diff_pos = $final_pos - $orig_pos; 216 while ( $diff_pos < 0 ) 217 array_splice( $final_rows, $orig_pos, 0, $diff_pos++ ); 218 } elseif ( $final_pos > $orig_pos ) { // This orig's match is down a ways. Pad orig with blank rows. 219 $diff_pos = $orig_pos - $final_pos; 220 while ( $diff_pos < 0 ) 221 array_splice( $orig_rows, $orig_pos, 0, $diff_pos++ ); 222 } 223 } 224 225 226 // Pad the ends with blank rows if the columns aren't the same length 227 $diff_count = count($orig_rows) - count($final_rows); 228 if ( $diff_count < 0 ) { 229 while ( $diff_count < 0 ) 230 array_push($orig_rows, $diff_count++); 231 } elseif ( $diff_count > 0 ) { 232 $diff_count = -1 * $diff_count; 233 while ( $diff_count < 0 ) 234 array_push($final_rows, $diff_count++); 235 } 236 237 return array($orig_matches, $final_matches, $orig_rows, $final_rows); 238 239 /* 240 // Debug 241 echo "\n\n\n\n\n"; 242 243 echo "-- DEBUG Matches: Orig -> Final --"; 244 245 foreach ( $orig_matches as $o => $f ) { 246 echo "\n\n\n\n\n"; 247 echo "ORIG: $o, FINAL: $f\n"; 248 var_dump($orig[$o],$final[$f]); 249 } 250 echo "\n\n\n\n\n"; 251 252 echo "-- DEBUG Matches: Final -> Orig --"; 253 254 foreach ( $final_matches as $f => $o ) { 255 echo "\n\n\n\n\n"; 256 echo "FINAL: $f, ORIG: $o\n"; 257 var_dump($final[$f],$orig[$o]); 258 } 259 echo "\n\n\n\n\n"; 260 261 echo "-- DEBUG Rows: Orig -- Final --"; 262 263 echo "\n\n\n\n\n"; 264 foreach ( $orig_rows as $row => $o ) { 265 if ( $o < 0 ) 266 $o = 'X'; 267 $f = $final_rows[$row]; 268 if ( $f < 0 ) 269 $f = 'X'; 270 echo "$o -- $f\n"; 271 } 272 echo "\n\n\n\n\n"; 273 274 echo "-- END DEBUG --"; 275 276 echo "\n\n\n\n\n"; 277 278 return array($orig_matches, $final_matches, $orig_rows, $final_rows); 279 */ 280 } 281 282 283 // Computes a number that is intended to reflect the "distance" between two strings. 284 function compute_string_distance( $string1, $string2 ) { 285 // Vectors containing character frequency for all chars in each string 286 $chars1 = count_chars($string1); 287 $chars2 = count_chars($string2); 288 289 // L1-norm of difference vector. 290 $difference = array_sum( array_map( array(&$this, 'difference'), $chars1, $chars2 ) ); 291 292 // $string1 has zero length? Odd. Give huge penalty by not dividing. 293 if ( !$string1 ) 294 return $difference; 295 296 // Return distance per charcter (of string1) 297 return $difference / strlen($string1); 298 } 299 300 function difference( $a, $b ) { 301 return abs( $a - $b ); 302 } 303 304 } 305 306 // Better word splitting than the PEAR package provides 307 class WP_Text_Diff_Renderer_inline extends Text_Diff_Renderer_inline { 308 309 function _splitOnWords($string, $newlineEscape = "\n") { 310 $string = str_replace("\0", '', $string); 311 $words = preg_split( '/([^\w])/', $string, -1, PREG_SPLIT_DELIM_CAPTURE ); 312 $words = str_replace( "\n", $newlineEscape, $words ); 313 return $words; 314 } 315 316 } 317 318 ?> -
wp-includes/link-template.php
old new 442 442 return $link; 443 443 } 444 444 445 function get_edit_post_link( $id = 0 ) {445 function get_edit_post_link( $id = 0, $context = 'display' ) { 446 446 if ( !$post = &get_post( $id ) ) 447 447 return; 448 448 449 if ( 'display' == $context ) 450 $action = 'action=edit&'; 451 else 452 $action = 'action=edit&'; 453 449 454 switch ( $post->post_type ) : 450 455 case 'page' : 451 456 if ( !current_user_can( 'edit_page', $post->ID ) ) … … 459 464 $file = 'media'; 460 465 $var = 'attachment_id'; 461 466 break; 467 case 'revision' : 468 if ( !current_user_can( 'edit_post', $post->ID ) ) 469 return; 470 $file = 'revision'; 471 $var = 'revision'; 472 $action = ''; 473 break; 462 474 default : 463 475 if ( !current_user_can( 'edit_post', $post->ID ) ) 464 476 return; … … 467 479 break; 468 480 endswitch; 469 481 470 return apply_filters( 'get_edit_post_link', get_bloginfo( 'wpurl' ) . "/wp-admin/$file.php? action=edit&$var=$post->ID", $post->ID );482 return apply_filters( 'get_edit_post_link', get_bloginfo( 'wpurl' ) . "/wp-admin/$file.php?{$action}$var=$post->ID", $post->ID ); 471 483 } 472 484 473 485 function edit_post_link( $link = 'Edit This', $before = '', $after = '' ) { -
wp-includes/Text/Diff/Engine/xdiff.php
old new 1 <?php 2 /** 3 * Class used internally by Diff to actually compute the diffs. 4 * 5 * This class uses the xdiff PECL package (http://pecl.php.net/package/xdiff) 6 * to compute the differences between the two input arrays. 7 * 8 * $Horde: framework/Text_Diff/Diff/Engine/xdiff.php,v 1.6 2008/01/04 10:07:50 jan Exp $ 9 * 10 * Copyright 2004-2008 The Horde Project (http://www.horde.org/) 11 * 12 * See the enclosed file COPYING for license information (LGPL). If you did 13 * not receive this file, see http://opensource.org/licenses/lgpl-license.php. 14 * 15 * @author Jon Parise <jon@horde.org> 16 * @package Text_Diff 17 */ 18 class Text_Diff_Engine_xdiff { 19 20 /** 21 */ 22 function diff($from_lines, $to_lines) 23 { 24 array_walk($from_lines, array('Text_Diff', 'trimNewlines')); 25 array_walk($to_lines, array('Text_Diff', 'trimNewlines')); 26 27 /* Convert the two input arrays into strings for xdiff processing. */ 28 $from_string = implode("\n", $from_lines); 29 $to_string = implode("\n", $to_lines); 30 31 /* Diff the two strings and convert the result to an array. */ 32 $diff = xdiff_string_diff($from_string, $to_string, count($to_lines)); 33 $diff = explode("\n", $diff); 34 35 /* Walk through the diff one line at a time. We build the $edits 36 * array of diff operations by reading the first character of the 37 * xdiff output (which is in the "unified diff" format). 38 * 39 * Note that we don't have enough information to detect "changed" 40 * lines using this approach, so we can't add Text_Diff_Op_changed 41 * instances to the $edits array. The result is still perfectly 42 * valid, albeit a little less descriptive and efficient. */ 43 $edits = array(); 44 foreach ($diff as $line) { 45 switch ($line[0]) { 46 case ' ': 47 $edits[] = &new Text_Diff_Op_copy(array(substr($line, 1))); 48 break; 49 50 case '+': 51 $edits[] = &new Text_Diff_Op_add(array(substr($line, 1))); 52 break; 53 54 case '-': 55 $edits[] = &new Text_Diff_Op_delete(array(substr($line, 1))); 56 break; 57 } 58 } 59 60 return $edits; 61 } 62 63 } -
wp-includes/Text/Diff/Engine/native.php
old new 1 <?php 2 /** 3 * $Horde: framework/Text_Diff/Diff/Engine/native.php,v 1.10 2008/01/04 10:27:53 jan Exp $ 4 * 5 * Class used internally by Text_Diff to actually compute the diffs. This 6 * class is implemented using native PHP code. 7 * 8 * The algorithm used here is mostly lifted from the perl module 9 * Algorithm::Diff (version 1.06) by Ned Konz, which is available at: 10 * http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip 11 * 12 * More ideas are taken from: http://www.ics.uci.edu/~eppstein/161/960229.html 13 * 14 * Some ideas (and a bit of code) are taken from analyze.c, of GNU 15 * diffutils-2.7, which can be found at: 16 * ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz 17 * 18 * Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from 19 * Geoffrey T. Dairiki <dairiki@dairiki.org>. The original PHP version of this 20 * code was written by him, and is used/adapted with his permission. 21 * 22 * Copyright 2004-2008 The Horde Project (http://www.horde.org/) 23 * 24 * See the enclosed file COPYING for license information (LGPL). If you did 25 * not receive this file, see http://opensource.org/licenses/lgpl-license.php. 26 * 27 * @author Geoffrey T. Dairiki <dairiki@dairiki.org> 28 * @package Text_Diff 29 */ 30 class Text_Diff_Engine_native { 31 32 function diff($from_lines, $to_lines) 33 { 34 array_walk($from_lines, array('Text_Diff', 'trimNewlines')); 35 array_walk($to_lines, array('Text_Diff', 'trimNewlines')); 36 37 $n_from = count($from_lines); 38 $n_to = count($to_lines); 39 40 $this->xchanged = $this->ychanged = array(); 41 $this->xv = $this->yv = array(); 42 $this->xind = $this->yind = array(); 43 unset($this->seq); 44 unset($this->in_seq); 45 unset($this->lcs); 46 47 // Skip leading common lines. 48 for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) { 49 if ($from_lines[$skip] !== $to_lines[$skip]) { 50 break; 51 } 52 $this->xchanged[$skip] = $this->ychanged[$skip] = false; 53 } 54 55 // Skip trailing common lines. 56 $xi = $n_from; $yi = $n_to; 57 for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) { 58 if ($from_lines[$xi] !== $to_lines[$yi]) { 59 break; 60 } 61 $this->xchanged[$xi] = $this->ychanged[$yi] = false; 62 } 63 64 // Ignore lines which do not exist in both files. 65 for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { 66 $xhash[$from_lines[$xi]] = 1; 67 } 68 for ($yi = $skip; $yi < $n_to - $endskip; $yi++) { 69 $line = $to_lines[$yi]; 70 if (($this->ychanged[$yi] = empty($xhash[$line]))) { 71 continue; 72 } 73 $yhash[$line] = 1; 74 $this->yv[] = $line; 75 $this->yind[] = $yi; 76 } 77 for ($xi = $skip; $xi < $n_from - $endskip; $xi++) { 78 $line = $from_lines[$xi]; 79 if (($this->xchanged[$xi] = empty($yhash[$line]))) { 80 continue; 81 } 82 $this->xv[] = $line; 83 $this->xind[] = $xi; 84 } 85 86 // Find the LCS. 87 $this->_compareseq(0, count($this->xv), 0, count($this->yv)); 88 89 // Merge edits when possible. 90 $this->_shiftBoundaries($from_lines, $this->xchanged, $this->ychanged); 91 $this->_shiftBoundaries($to_lines, $this->ychanged, $this->xchanged); 92 93 // Compute the edit operations. 94 $edits = array(); 95 $xi = $yi = 0; 96 while ($xi < $n_from || $yi < $n_to) { 97 assert($yi < $n_to || $this->xchanged[$xi]); 98 assert($xi < $n_from || $this->ychanged[$yi]); 99 100 // Skip matching "snake". 101 $copy = array(); 102 while ($xi < $n_from && $yi < $n_to 103 && !$this->xchanged[$xi] && !$this->ychanged[$yi]) { 104 $copy[] = $from_lines[$xi++]; 105 ++$yi; 106 } 107 if ($copy) { 108 $edits[] = &new Text_Diff_Op_copy($copy); 109 } 110 111 // Find deletes & adds. 112 $delete = array(); 113 while ($xi < $n_from && $this->xchanged[$xi]) { 114 $delete[] = $from_lines[$xi++]; 115 } 116 117 $add = array(); 118 while ($yi < $n_to && $this->ychanged[$yi]) { 119 $add[] = $to_lines[$yi++]; 120 } 121 122 if ($delete && $add) { 123 $edits[] = &new Text_Diff_Op_change($delete, $add); 124 } elseif ($delete) { 125 $edits[] = &new Text_Diff_Op_delete($delete); 126 } elseif ($add) { 127 $edits[] = &new Text_Diff_Op_add($add); 128 } 129 } 130 131 return $edits; 132 } 133 134 /** 135 * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF, 136 * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized 137 * segments. 138 * 139 * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of 140 * NCHUNKS+1 (X, Y) indexes giving the diving points between sub 141 * sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1), 142 * the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) == 143 * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM).
