Title: WP_Text_Diff_Renderer_Table::interleave_changed_lines
Published: April 25, 2014
Last modified: May 20, 2026

---

# WP_Text_Diff_Renderer_Table::interleave_changed_lines( array $orig, array $final ): array

## In this article

 * [Parameters](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#parameters)
 * [Return](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#return)
 * [Source](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#source)
 * [Related](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#related)
 * [Changelog](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#changelog)

[ Back to top](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#wp--skip-link--target)

Takes changed blocks and matches which rows in orig turned into which rows in final.

## 󠀁[Parameters](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#parameters)󠁿

 `$orig`arrayrequired

Lines of the original version of the text.

`$final`arrayrequired

Lines of the final version of the text.

## 󠀁[Return](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#return)󠁿

 array Array containing results of comparing the original text to the final text.

 * `orig_matches` array
 * Associative array of original matches. Index == row number of `$orig`, value 
   == corresponding row number of that same line in `$final` or `'x'` if there is
   no corresponding row (indicating it is a deleted line).
 * `final_matches` array
 * Associative array of final matches. Index == row number of `$final`, value ==
   corresponding row number of that same line in `$orig` or `'x'` if there is no
   corresponding row (indicating it is a new line).
 * `orig_rows` array
 * Associative array of interleaved rows of `$orig` with blanks to keep matches 
   aligned with side-by-side diff of `$final`. A value >= 0 corresponds to index
   of `$orig`.
    Value < 0 indicates a blank row.
 * `final_rows` array
 * Associative array of interleaved rows of `$final` with blanks to keep matches
   aligned with side-by-side diff of `$orig`. A value >= 0 corresponds to index 
   of `$final`.
    Value < 0 indicates a blank row.

## 󠀁[Source](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#source)󠁿

    ```php
    public function interleave_changed_lines( $orig, $final ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.finalFound

    	// Contains all pairwise string comparisons. Keys are such that this need only be a one dimensional array.
    	$matches = array();
    	foreach ( array_keys( $orig ) as $o ) {
    		foreach ( array_keys( $final ) as $f ) {
    			$matches[ "$o,$f" ] = $this->compute_string_distance( $orig[ $o ], $final[ $f ] );
    		}
    	}
    	asort( $matches ); // Order by string distance.

    	$orig_matches  = array();
    	$final_matches = array();

    	foreach ( $matches as $keys => $difference ) {
    		list($o, $f) = explode( ',', $keys );
    		$o           = (int) $o;
    		$f           = (int) $f;

    		// Already have better matches for these guys.
    		if ( isset( $orig_matches[ $o ] ) && isset( $final_matches[ $f ] ) ) {
    			continue;
    		}

    		// First match for these guys. Must be best match.
    		if ( ! isset( $orig_matches[ $o ] ) && ! isset( $final_matches[ $f ] ) ) {
    			$orig_matches[ $o ]  = $f;
    			$final_matches[ $f ] = $o;
    			continue;
    		}

    		// Best match of this final is already taken? Must mean this final is a new row.
    		if ( isset( $orig_matches[ $o ] ) ) {
    			$final_matches[ $f ] = 'x';
    		} elseif ( isset( $final_matches[ $f ] ) ) {
    			// Best match of this orig is already taken? Must mean this orig is a deleted row.
    			$orig_matches[ $o ] = 'x';
    		}
    	}

    	// We read the text in this order.
    	ksort( $orig_matches );
    	ksort( $final_matches );

    	// Stores rows and blanks for each column.
    	$orig_rows      = array_keys( $orig_matches );
    	$orig_rows_copy = $orig_rows;
    	$final_rows     = array_keys( $final_matches );

    	/*
    	 * Interleaves rows with blanks to keep matches aligned.
    	 * We may end up with some extraneous blank rows, but we'll just ignore them later.
    	 */
    	foreach ( $orig_rows_copy as $orig_row ) {
    		$final_pos = array_search( $orig_matches[ $orig_row ], $final_rows, true );
    		$orig_pos  = (int) array_search( $orig_row, $orig_rows, true );

    		if ( false === $final_pos ) { // This orig is paired with a blank final.
    			array_splice( $final_rows, $orig_pos, 0, -1 );
    		} elseif ( $final_pos < $orig_pos ) { // This orig's match is up a ways. Pad final with blank rows.
    			$diff_array = range( -1, $final_pos - $orig_pos );
    			array_splice( $final_rows, $orig_pos, 0, $diff_array );
    		} elseif ( $final_pos > $orig_pos ) { // This orig's match is down a ways. Pad orig with blank rows.
    			$diff_array = range( -1, $orig_pos - $final_pos );
    			array_splice( $orig_rows, $orig_pos, 0, $diff_array );
    		}
    	}

    	// Pad the ends with blank rows if the columns aren't the same length.
    	$diff_count = count( $orig_rows ) - count( $final_rows );
    	if ( $diff_count < 0 ) {
    		while ( $diff_count < 0 ) {
    			array_push( $orig_rows, $diff_count++ );
    		}
    	} elseif ( $diff_count > 0 ) {
    		$diff_count = -1 * $diff_count;
    		while ( $diff_count < 0 ) {
    			array_push( $final_rows, $diff_count++ );
    		}
    	}

    	return array( $orig_matches, $final_matches, $orig_rows, $final_rows );
    }
    ```

[View all references](https://developer.wordpress.org/reference/files/wp-includes/class-wp-text-diff-renderer-table.php/)
[View on Trac](https://core.trac.wordpress.org/browser/tags/7.0/src/wp-includes/class-wp-text-diff-renderer-table.php#L400)
[View on GitHub](https://github.com/WordPress/wordpress-develop/blob/7.0/src/wp-includes/class-wp-text-diff-renderer-table.php#L400-L482)

## 󠀁[Related](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#related)󠁿

| Uses | Description | 
| [WP_Text_Diff_Renderer_Table::compute_string_distance()](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/compute_string_distance/)`wp-includes/class-wp-text-diff-renderer-table.php` |

Computes a number that is intended to reflect the “distance” between two strings.

  |

| Used by | Description | 
| [WP_Text_Diff_Renderer_Table::_changed()](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/_changed/)`wp-includes/class-wp-text-diff-renderer-table.php` |

Process changed lines to do word-by-word diffs for extra highlighting.

  |

## 󠀁[Changelog](https://developer.wordpress.org/reference/classes/wp_text_diff_renderer_table/interleave_changed_lines/?output_format=md#changelog)󠁿

| Version | Description | 
| [2.6.0](https://developer.wordpress.org/reference/since/2.6.0/) | Introduced. |

## User Contributed Notes

You must [log in](https://login.wordpress.org/?redirect_to=https%3A%2F%2Fdeveloper.wordpress.org%2Freference%2Fclasses%2Fwp_text_diff_renderer_table%2Finterleave_changed_lines%2F)
before being able to contribute a note or feedback.