wp/wp-includes/wp-diff.php
changeset 5 5e2f62d02dcd
parent 0 d970ebf37754
child 7 cf61fcea0001
equal deleted inserted replaced
4:346c88efed21 5:5e2f62d02dcd
    26 class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
    26 class WP_Text_Diff_Renderer_Table extends Text_Diff_Renderer {
    27 
    27 
    28 	/**
    28 	/**
    29 	 * @see Text_Diff_Renderer::_leading_context_lines
    29 	 * @see Text_Diff_Renderer::_leading_context_lines
    30 	 * @var int
    30 	 * @var int
    31 	 * @access protected
    31 	 * @access public
    32 	 * @since 2.6.0
    32 	 * @since 2.6.0
    33 	 */
    33 	 */
    34 	var $_leading_context_lines  = 10000;
    34 	public $_leading_context_lines  = 10000;
    35 
    35 
    36 	/**
    36 	/**
    37 	 * @see Text_Diff_Renderer::_trailing_context_lines
    37 	 * @see Text_Diff_Renderer::_trailing_context_lines
    38 	 * @var int
    38 	 * @var int
    39 	 * @access protected
    39 	 * @access public
    40 	 * @since 2.6.0
    40 	 * @since 2.6.0
    41 	 */
    41 	 */
    42 	var $_trailing_context_lines = 10000;
    42 	public $_trailing_context_lines = 10000;
    43 
    43 
    44 	/**
    44 	/**
    45 	 * {@internal Missing Description}}
    45 	 * Threshold for when a diff should be saved or omitted.
    46 	 *
    46 	 *
    47 	 * @var float
    47 	 * @var float
    48 	 * @access protected
    48 	 * @access protected
    49 	 * @since 2.6.0
    49 	 * @since 2.6.0
    50 	 */
    50 	 */
    51 	var $_diff_threshold = 0.6;
    51 	protected $_diff_threshold = 0.6;
    52 
    52 
    53 	/**
    53 	/**
    54 	 * Inline display helper object name.
    54 	 * Inline display helper object name.
    55 	 *
    55 	 *
    56 	 * @var string
    56 	 * @var string
    57 	 * @access protected
    57 	 * @access protected
    58 	 * @since 2.6.0
    58 	 * @since 2.6.0
    59 	 */
    59 	 */
    60 	var $inline_diff_renderer = 'WP_Text_Diff_Renderer_inline';
    60 	protected $inline_diff_renderer = 'WP_Text_Diff_Renderer_inline';
    61 
    61 
    62 	/**
    62 	/**
    63 	 * Should we show the split view or not
    63 	 * Should we show the split view or not
    64 	 *
    64 	 *
    65 	 * @var string
    65 	 * @var string
    66 	 * @access protected
    66 	 * @access protected
    67 	 * @since 3.6.0
    67 	 * @since 3.6.0
    68 	 */
    68 	 */
    69 	var $_show_split_view = true;
    69 	protected $_show_split_view = true;
       
    70 
       
    71 	protected $compat_fields = array( '_show_split_view', 'inline_diff_renderer', '_diff_threshold' );
    70 
    72 
    71 	/**
    73 	/**
    72 	 * Constructor - Call parent constructor with params array.
    74 	 * Constructor - Call parent constructor with params array.
    73 	 *
    75 	 *
    74 	 * This will set class properties based on the key value pairs in the array.
    76 	 * This will set class properties based on the key value pairs in the array.
    75 	 *
    77 	 *
    76 	 * @since 2.6.0
    78 	 * @since 2.6.0
    77 	 *
    79 	 *
    78 	 * @param array $params
    80 	 * @param array $params
    79 	 */
    81 	 */
    80 	function __construct( $params = array() ) {
    82 	public function __construct( $params = array() ) {
    81 		parent::__construct( $params );
    83 		parent::__construct( $params );
    82 		if ( isset( $params[ 'show_split_view' ] ) )
    84 		if ( isset( $params[ 'show_split_view' ] ) )
    83 			$this->_show_split_view = $params[ 'show_split_view' ];
    85 			$this->_show_split_view = $params[ 'show_split_view' ];
    84 	}
    86 	}
    85 
    87 
    87 	 * @ignore
    89 	 * @ignore
    88 	 *
    90 	 *
    89 	 * @param string $header
    91 	 * @param string $header
    90 	 * @return string
    92 	 * @return string
    91 	 */
    93 	 */
    92 	function _startBlock( $header ) {
    94 	public function _startBlock( $header ) {
    93 		return '';
    95 		return '';
    94 	}
    96 	}
    95 
    97 
    96 	/**
    98 	/**
    97 	 * @ignore
    99 	 * @ignore
    98 	 *
   100 	 *
    99 	 * @param array $lines
   101 	 * @param array $lines
   100 	 * @param string $prefix
   102 	 * @param string $prefix
   101 	 */
   103 	 */
   102 	function _lines( $lines, $prefix=' ' ) {
   104 	public function _lines( $lines, $prefix=' ' ) {
   103 	}
   105 	}
   104 
   106 
   105 	/**
   107 	/**
   106 	 * @ignore
   108 	 * @ignore
   107 	 *
   109 	 *
   108 	 * @param string $line HTML-escape the value.
   110 	 * @param string $line HTML-escape the value.
   109 	 * @return string
   111 	 * @return string
   110 	 */
   112 	 */
   111 	function addedLine( $line ) {
   113 	public function addedLine( $line ) {
   112 		return "<td class='diff-addedline'>{$line}</td>";
   114 		return "<td class='diff-addedline'>{$line}</td>";
   113 
   115 
   114 	}
   116 	}
   115 
   117 
   116 	/**
   118 	/**
   117 	 * @ignore
   119 	 * @ignore
   118 	 *
   120 	 *
   119 	 * @param string $line HTML-escape the value.
   121 	 * @param string $line HTML-escape the value.
   120 	 * @return string
   122 	 * @return string
   121 	 */
   123 	 */
   122 	function deletedLine( $line ) {
   124 	public function deletedLine( $line ) {
   123 		return "<td class='diff-deletedline'>{$line}</td>";
   125 		return "<td class='diff-deletedline'>{$line}</td>";
   124 	}
   126 	}
   125 
   127 
   126 	/**
   128 	/**
   127 	 * @ignore
   129 	 * @ignore
   128 	 *
   130 	 *
   129 	 * @param string $line HTML-escape the value.
   131 	 * @param string $line HTML-escape the value.
   130 	 * @return string
   132 	 * @return string
   131 	 */
   133 	 */
   132 	function contextLine( $line ) {
   134 	public function contextLine( $line ) {
   133 		return "<td class='diff-context'>{$line}</td>";
   135 		return "<td class='diff-context'>{$line}</td>";
   134 	}
   136 	}
   135 
   137 
   136 	/**
   138 	/**
   137 	 * @ignore
   139 	 * @ignore
   138 	 *
   140 	 *
   139 	 * @return string
   141 	 * @return string
   140 	 */
   142 	 */
   141 	function emptyLine() {
   143 	public function emptyLine() {
   142 		return '<td>&nbsp;</td>';
   144 		return '<td>&nbsp;</td>';
   143 	}
   145 	}
   144 
   146 
   145 	/**
   147 	/**
   146 	 * @ignore
   148 	 * @ignore
   147 	 * @access private
   149 	 * @access public
   148 	 *
   150 	 *
   149 	 * @param array $lines
   151 	 * @param array $lines
   150 	 * @param bool $encode
   152 	 * @param bool $encode
   151 	 * @return string
   153 	 * @return string
   152 	 */
   154 	 */
   153 	function _added( $lines, $encode = true ) {
   155 	public function _added( $lines, $encode = true ) {
   154 		$r = '';
   156 		$r = '';
   155 		foreach ($lines as $line) {
   157 		foreach ($lines as $line) {
   156 			if ( $encode )
   158 			if ( $encode ) {
   157 				$line = htmlspecialchars( $line );
   159 				$processed_line = htmlspecialchars( $line );
       
   160 
       
   161 				/**
       
   162 				 * Contextually filter a diffed line.
       
   163 				 *
       
   164 				 * Filters TextDiff processing of diffed line. By default, diffs are processed with
       
   165 				 * htmlspecialchars. Use this filter to remove or change the processing. Passes a context
       
   166 				 * indicating if the line is added, deleted or unchanged.
       
   167 				 *
       
   168 				 * @since 4.1.0
       
   169 				 *
       
   170 				 * @param String $processed_line The processed diffed line.
       
   171 				 * @param String $line           The unprocessed diffed line.
       
   172 		 		 * @param string null            The line context. Values are 'added', 'deleted' or 'unchanged'.
       
   173 				 */
       
   174 				$line = apply_filters( 'process_text_diff_html', $processed_line, $line, 'added' );
       
   175 			}
       
   176 
   158 			if ( $this->_show_split_view ) {
   177 			if ( $this->_show_split_view ) {
   159 				$r .= '<tr>' . $this->emptyLine() . $this->emptyLine() . $this->addedLine( $line ) . "</tr>\n";
   178 				$r .= '<tr>' . $this->emptyLine() . $this->emptyLine() . $this->addedLine( $line ) . "</tr>\n";
   160 			} else {
   179 			} else {
   161 				$r .= '<tr>' . $this->addedLine( $line ) . "</tr>\n";
   180 				$r .= '<tr>' . $this->addedLine( $line ) . "</tr>\n";
   162 			}
   181 			}
   164 		return $r;
   183 		return $r;
   165 	}
   184 	}
   166 
   185 
   167 	/**
   186 	/**
   168 	 * @ignore
   187 	 * @ignore
   169 	 * @access private
   188 	 * @access public
   170 	 *
   189 	 *
   171 	 * @param array $lines
   190 	 * @param array $lines
   172 	 * @param bool $encode
   191 	 * @param bool $encode
   173 	 * @return string
   192 	 * @return string
   174 	 */
   193 	 */
   175 	function _deleted( $lines, $encode = true ) {
   194 	public function _deleted( $lines, $encode = true ) {
   176 		$r = '';
   195 		$r = '';
   177 		foreach ($lines as $line) {
   196 		foreach ($lines as $line) {
   178 			if ( $encode )
   197 			if ( $encode ) {
   179 				$line = htmlspecialchars( $line );
   198 				$processed_line = htmlspecialchars( $line );
       
   199 
       
   200 				/** This filter is documented in wp-includes/wp-diff.php */
       
   201 				$line = apply_filters( 'process_text_diff_html', $processed_line, $line, 'deleted' );
       
   202 			}
   180 			if ( $this->_show_split_view ) {
   203 			if ( $this->_show_split_view ) {
   181 				$r .= '<tr>' . $this->deletedLine( $line ) . $this->emptyLine() . $this->emptyLine() . "</tr>\n";
   204 				$r .= '<tr>' . $this->deletedLine( $line ) . $this->emptyLine() . $this->emptyLine() . "</tr>\n";
   182 			} else {
   205 			} else {
   183 				$r .= '<tr>' . $this->deletedLine( $line ) . "</tr>\n";
   206 				$r .= '<tr>' . $this->deletedLine( $line ) . "</tr>\n";
   184 			}
   207 			}
   187 		return $r;
   210 		return $r;
   188 	}
   211 	}
   189 
   212 
   190 	/**
   213 	/**
   191 	 * @ignore
   214 	 * @ignore
   192 	 * @access private
   215 	 * @access public
   193 	 *
   216 	 *
   194 	 * @param array $lines
   217 	 * @param array $lines
   195 	 * @param bool $encode
   218 	 * @param bool $encode
   196 	 * @return string
   219 	 * @return string
   197 	 */
   220 	 */
   198 	function _context( $lines, $encode = true ) {
   221 	public function _context( $lines, $encode = true ) {
   199 		$r = '';
   222 		$r = '';
   200 		foreach ($lines as $line) {
   223 		foreach ($lines as $line) {
   201 			if ( $encode )
   224 			if ( $encode ) {
   202 				$line = htmlspecialchars( $line );
   225 				$processed_line = htmlspecialchars( $line );
       
   226 
       
   227 				/** This filter is documented in wp-includes/wp-diff.php */
       
   228 				$line = apply_filters( 'process_text_diff_html', $processed_line, $line, 'unchanged' );
       
   229 			}
   203 			if (  $this->_show_split_view ) {
   230 			if (  $this->_show_split_view ) {
   204 				$r .= '<tr>' . $this->contextLine( $line ) . $this->emptyLine() . $this->contextLine( $line )  . "</tr>\n";
   231 				$r .= '<tr>' . $this->contextLine( $line ) . $this->emptyLine() . $this->contextLine( $line )  . "</tr>\n";
   205 			} else {
   232 			} else {
   206 				$r .= '<tr>' . $this->contextLine( $line ) . "</tr>\n";
   233 				$r .= '<tr>' . $this->contextLine( $line ) . "</tr>\n";
   207 			}
   234 			}
   213 	 * Process changed lines to do word-by-word diffs for extra highlighting.
   240 	 * Process changed lines to do word-by-word diffs for extra highlighting.
   214 	 *
   241 	 *
   215 	 * (TRAC style) sometimes these lines can actually be deleted or added rows.
   242 	 * (TRAC style) sometimes these lines can actually be deleted or added rows.
   216 	 * We do additional processing to figure that out
   243 	 * We do additional processing to figure that out
   217 	 *
   244 	 *
   218 	 * @access private
   245 	 * @access public
   219 	 * @since 2.6.0
   246 	 * @since 2.6.0
   220 	 *
   247 	 *
   221 	 * @param array $orig
   248 	 * @param array $orig
   222 	 * @param array $final
   249 	 * @param array $final
   223 	 * @return string
   250 	 * @return string
   224 	 */
   251 	 */
   225 	function _changed( $orig, $final ) {
   252 	public function _changed( $orig, $final ) {
   226 		$r = '';
   253 		$r = '';
   227 
   254 
   228 		// Does the aforementioned additional processing
   255 		// Does the aforementioned additional processing
   229 		// *_matches tell what rows are "the same" in orig and final. Those pairs will be diffed to get word changes
   256 		// *_matches tell what rows are "the same" in orig and final. Those pairs will be diffed to get word changes
   230 		//	match is numeric: an index in other column
   257 		//	match is numeric: an index in other column
   244 				$text_diff = new Text_Diff( 'auto', array( array($orig[$o]), array($final[$f]) ) );
   271 				$text_diff = new Text_Diff( 'auto', array( array($orig[$o]), array($final[$f]) ) );
   245 				$renderer = new $this->inline_diff_renderer;
   272 				$renderer = new $this->inline_diff_renderer;
   246 				$diff = $renderer->render( $text_diff );
   273 				$diff = $renderer->render( $text_diff );
   247 
   274 
   248 				// If they're too different, don't include any <ins> or <dels>
   275 				// If they're too different, don't include any <ins> or <dels>
   249 				if ( $diff_count = preg_match_all( '!(<ins>.*?</ins>|<del>.*?</del>)!', $diff, $diff_matches ) ) {
   276 				if ( preg_match_all( '!(<ins>.*?</ins>|<del>.*?</del>)!', $diff, $diff_matches ) ) {
   250 					// length of all text between <ins> or <del>
   277 					// length of all text between <ins> or <del>
   251 					$stripped_matches = strlen(strip_tags( join(' ', $diff_matches[0]) ));
   278 					$stripped_matches = strlen(strip_tags( join(' ', $diff_matches[0]) ));
   252 					// since we count lengith of text between <ins> or <del> (instead of picking just one),
   279 					// since we count lengith of text between <ins> or <del> (instead of picking just one),
   253 					//	we double the length of chars not in those tags.
   280 					//	we double the length of chars not in those tags.
   254 					$stripped_diff = strlen(strip_tags( $diff )) * 2 - $stripped_matches;
   281 					$stripped_diff = strlen(strip_tags( $diff )) * 2 - $stripped_matches;
   307 	 *	*_rows ( order of rows in each column interleaved with blank rows as
   334 	 *	*_rows ( order of rows in each column interleaved with blank rows as
   308 	 *		necessary )
   335 	 *		necessary )
   309 	 *
   336 	 *
   310 	 * @since 2.6.0
   337 	 * @since 2.6.0
   311 	 *
   338 	 *
   312 	 * @param unknown_type $orig
   339 	 * @param array $orig
   313 	 * @param unknown_type $final
   340 	 * @param array $final
   314 	 * @return unknown
   341 	 * @return array
   315 	 */
   342 	 */
   316 	function interleave_changed_lines( $orig, $final ) {
   343 	public function interleave_changed_lines( $orig, $final ) {
   317 
   344 
   318 		// Contains all pairwise string comparisons. Keys are such that this need only be a one dimensional array.
   345 		// Contains all pairwise string comparisons. Keys are such that this need only be a one dimensional array.
   319 		$matches = array();
   346 		$matches = array();
   320 		foreach ( array_keys($orig) as $o ) {
   347 		foreach ( array_keys($orig) as $o ) {
   321 			foreach ( array_keys($final) as $f ) {
   348 			foreach ( array_keys($final) as $f ) {
   389 			while ( $diff_count < 0 )
   416 			while ( $diff_count < 0 )
   390 				array_push($final_rows, $diff_count++);
   417 				array_push($final_rows, $diff_count++);
   391 		}
   418 		}
   392 
   419 
   393 		return array($orig_matches, $final_matches, $orig_rows, $final_rows);
   420 		return array($orig_matches, $final_matches, $orig_rows, $final_rows);
   394 
       
   395 /*
       
   396 		// Debug
       
   397 		echo "\n\n\n\n\n";
       
   398 
       
   399 		echo "-- DEBUG Matches: Orig -> Final --";
       
   400 
       
   401 		foreach ( $orig_matches as $o => $f ) {
       
   402 			echo "\n\n\n\n\n";
       
   403 			echo "ORIG: $o, FINAL: $f\n";
       
   404 			var_dump($orig[$o],$final[$f]);
       
   405 		}
       
   406 		echo "\n\n\n\n\n";
       
   407 
       
   408 		echo "-- DEBUG Matches: Final -> Orig --";
       
   409 
       
   410 		foreach ( $final_matches as $f => $o ) {
       
   411 			echo "\n\n\n\n\n";
       
   412 			echo "FINAL: $f, ORIG: $o\n";
       
   413 			var_dump($final[$f],$orig[$o]);
       
   414 		}
       
   415 		echo "\n\n\n\n\n";
       
   416 
       
   417 		echo "-- DEBUG Rows: Orig -- Final --";
       
   418 
       
   419 		echo "\n\n\n\n\n";
       
   420 		foreach ( $orig_rows as $row => $o ) {
       
   421 			if ( $o < 0 )
       
   422 				$o = 'X';
       
   423 			$f = $final_rows[$row];
       
   424 			if ( $f < 0 )
       
   425 				$f = 'X';
       
   426 			echo "$o -- $f\n";
       
   427 		}
       
   428 		echo "\n\n\n\n\n";
       
   429 
       
   430 		echo "-- END DEBUG --";
       
   431 
       
   432 		echo "\n\n\n\n\n";
       
   433 
       
   434 		return array($orig_matches, $final_matches, $orig_rows, $final_rows);
       
   435 */
       
   436 	}
   421 	}
   437 
   422 
   438 	/**
   423 	/**
   439 	 * Computes a number that is intended to reflect the "distance" between two strings.
   424 	 * Computes a number that is intended to reflect the "distance" between two strings.
   440 	 *
   425 	 *
   442 	 *
   427 	 *
   443 	 * @param string $string1
   428 	 * @param string $string1
   444 	 * @param string $string2
   429 	 * @param string $string2
   445 	 * @return int
   430 	 * @return int
   446 	 */
   431 	 */
   447 	function compute_string_distance( $string1, $string2 ) {
   432 	public function compute_string_distance( $string1, $string2 ) {
   448 		// Vectors containing character frequency for all chars in each string
   433 		// Vectors containing character frequency for all chars in each string
   449 		$chars1 = count_chars($string1);
   434 		$chars1 = count_chars($string1);
   450 		$chars2 = count_chars($string2);
   435 		$chars2 = count_chars($string2);
   451 
   436 
   452 		// L1-norm of difference vector.
   437 		// L1-norm of difference vector.
   454 
   439 
   455 		// $string1 has zero length? Odd. Give huge penalty by not dividing.
   440 		// $string1 has zero length? Odd. Give huge penalty by not dividing.
   456 		if ( !$string1 )
   441 		if ( !$string1 )
   457 			return $difference;
   442 			return $difference;
   458 
   443 
   459 		// Return distance per charcter (of string1)
   444 		// Return distance per character (of string1).
   460 		return $difference / strlen($string1);
   445 		return $difference / strlen($string1);
   461 	}
   446 	}
   462 
   447 
   463 	/**
   448 	/**
   464 	 * @ignore
   449 	 * @ignore
   466 	 *
   451 	 *
   467 	 * @param int $a
   452 	 * @param int $a
   468 	 * @param int $b
   453 	 * @param int $b
   469 	 * @return int
   454 	 * @return int
   470 	 */
   455 	 */
   471 	function difference( $a, $b ) {
   456 	public function difference( $a, $b ) {
   472 		return abs( $a - $b );
   457 		return abs( $a - $b );
   473 	}
   458 	}
   474 
   459 
       
   460 	/**
       
   461 	 * Make private properties readable for backwards compatibility.
       
   462 	 *
       
   463 	 * @since 4.0.0
       
   464 	 * @access public
       
   465 	 *
       
   466 	 * @param string $name Property to get.
       
   467 	 * @return mixed Property.
       
   468 	 */
       
   469 	public function __get( $name ) {
       
   470 		if ( in_array( $name, $this->compat_fields ) ) {
       
   471 			return $this->$name;
       
   472 		}
       
   473 	}
       
   474 
       
   475 	/**
       
   476 	 * Make private properties settable for backwards compatibility.
       
   477 	 *
       
   478 	 * @since 4.0.0
       
   479 	 * @access public
       
   480 	 *
       
   481 	 * @param string $name  Property to check if set.
       
   482 	 * @param mixed  $value Property value.
       
   483 	 * @return mixed Newly-set property.
       
   484 	 */
       
   485 	public function __set( $name, $value ) {
       
   486 		if ( in_array( $name, $this->compat_fields ) ) {
       
   487 			return $this->$name = $value;
       
   488 		}
       
   489 	}
       
   490 
       
   491 	/**
       
   492 	 * Make private properties checkable for backwards compatibility.
       
   493 	 *
       
   494 	 * @since 4.0.0
       
   495 	 * @access public
       
   496 	 *
       
   497 	 * @param string $name Property to check if set.
       
   498 	 * @return bool Whether the property is set.
       
   499 	 */
       
   500 	public function __isset( $name ) {
       
   501 		if ( in_array( $name, $this->compat_fields ) ) {
       
   502 			return isset( $this->$name );
       
   503 		}
       
   504 	}
       
   505 
       
   506 	/**
       
   507 	 * Make private properties un-settable for backwards compatibility.
       
   508 	 *
       
   509 	 * @since 4.0.0
       
   510 	 * @access public
       
   511 	 *
       
   512 	 * @param string $name Property to unset.
       
   513 	 */
       
   514 	public function __unset( $name ) {
       
   515 		if ( in_array( $name, $this->compat_fields ) ) {
       
   516 			unset( $this->$name );
       
   517 		}
       
   518 	}
   475 }
   519 }
   476 
   520 
   477 /**
   521 /**
   478  * Better word splitting than the PEAR package provides.
   522  * Better word splitting than the PEAR package provides.
   479  *
   523  *
   488 	 *
   532 	 *
   489 	 * @param string $string
   533 	 * @param string $string
   490 	 * @param string $newlineEscape
   534 	 * @param string $newlineEscape
   491 	 * @return string
   535 	 * @return string
   492 	 */
   536 	 */
   493 	function _splitOnWords($string, $newlineEscape = "\n") {
   537 	public function _splitOnWords($string, $newlineEscape = "\n") {
   494 		$string = str_replace("\0", '', $string);
   538 		$string = str_replace("\0", '', $string);
   495 		$words  = preg_split( '/([^\w])/u', $string, -1, PREG_SPLIT_DELIM_CAPTURE );
   539 		$words  = preg_split( '/([^\w])/u', $string, -1, PREG_SPLIT_DELIM_CAPTURE );
   496 		$words  = str_replace( "\n", $newlineEscape, $words );
   540 		$words  = str_replace( "\n", $newlineEscape, $words );
   497 		return $words;
   541 		return $words;
   498 	}
   542 	}