/** * Computes the two textes and returns an array with the changes needed * to trade back to the old text. * * @author Johannes Klose <*****@*****.**> * @param string $text1 The old text * @param string $text2 The new text * @return array Differences between $text1 and $text2 **/ function getDiff($text1, $text2) { $lines1 = explode("\n", $text1); $lines2 = explode("\n", $text2); $obj = new Text_Diff($lines2, $lines1); $diff = $obj->getDiff(); $ndiff = array(); $lines = 0; /** * Take the array with the differences and strip * informations (unchanged lines, old values on changed lines) * we do not need to store in the database to get from the * new page version to the old one. **/ foreach ($diff as $op) { if (strtolower(get_class($op)) == 'text_diff_op_copy') { $lines += count($op->orig); continue; } elseif (strtolower(get_class($op)) == 'text_diff_op_change') { if (count($op->orig) == count($op->final)) { foreach ($op->final as $key => $val) { if (isset($op->orig[$key])) { $ndiff[$lines + $key] = array('~', $val); } else { $ndiff[$lines + $key] = array('+', $val); } } } elseif (count($op->orig) > count($op->final)) { foreach ($op->orig as $key => $val) { if (isset($op->final[$key])) { $ndiff[$lines + $key] = array('~', $op->final[$key]); } else { $ndiff[$lines + $key] = array('-'); } } } else { foreach ($op->final as $key => $val) { if (isset($op->orig[$key])) { $ndiff[$lines + $key] = array('~', $op->final[$key]); } else { $ndiff[$lines + $key] = array('+', $op->final[$key]); } } } } elseif (strtolower(get_class($op)) == 'text_diff_op_add') { foreach ($op->final as $key => $val) { $ndiff[$lines + $key] = array('+', $val); } } elseif (strtolower(get_class($op)) == 'text_diff_op_delete') { foreach ($op->orig as $key => $val) { $ndiff[$lines + $key] = array('-'); } } $lines += count($op->orig) > count($op->final) ? count($op->orig) : count($op->final); } return $ndiff; }
/** * Renders a diff. * * @param Text_Diff $diff A Text_Diff object. * * @return string The formatted output. */ function render($diff) { $xi = $yi = 1; $block = false; $context = array(); $nlead = $this->_leading_context_lines; $ntrail = $this->_trailing_context_lines; $output = $this->_startDiff(); $diffs = $diff->getDiff(); foreach ($diffs as $i => $edit) { if (is_a($edit, 'Text_Diff_Op_copy')) { if (is_array($block)) { $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail; if (count($edit->orig) <= $keep) { $block[] = $edit; } else { if ($ntrail) { $context = array_slice($edit->orig, 0, $ntrail); $block[] =& new Text_Diff_Op_copy($context); } $output .= $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block); $block = false; } } $context = $edit->orig; } else { if (!is_array($block)) { $context = array_slice($context, count($context) - $nlead); $x0 = $xi - count($context); $y0 = $yi - count($context); $block = array(); if ($context) { $block[] =& new Text_Diff_Op_copy($context); } } $block[] = $edit; } if ($edit->orig) { $xi += count($edit->orig); } if ($edit->final) { $yi += count($edit->final); } } if (is_array($block)) { $output .= $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block); } return $output . $this->_endDiff(); }
/** * Computes a diff between sequences of strings. * * This can be used to compute things like case-insensitve diffs, or diffs * which ignore changes in white-space. * * @param array $from_lines An array of strings. * @param array $to_lines An array of strings. * @param array $mapped_from_lines This array should have the same size * number of elements as $from_lines. The * elements in $mapped_from_lines and * $mapped_to_lines are what is actually * compared when computing the diff. * @param array $mapped_to_lines This array should have the same number * of elements as $to_lines. */ function Text_Diff_Mapped($from_lines, $to_lines, $mapped_from_lines, $mapped_to_lines) { assert(count($from_lines) == count($mapped_from_lines)); assert(count($to_lines) == count($mapped_to_lines)); parent::Text_Diff($mapped_from_lines, $mapped_to_lines); $xi = $yi = 0; for ($i = 0; $i < count($this->_edits); $i++) { $orig =& $this->_edits[$i]->orig; if (is_array($orig)) { $orig = array_slice($from_lines, $xi, count($orig)); $xi += count($orig); } $final =& $this->_edits[$i]->final; if (is_array($final)) { $final = array_slice($to_lines, $yi, count($final)); $yi += count($final); } } }
/** * Renders a diff. * * @param Text_Diff $diff A Text_Diff object. * * @return string The formatted output. */ function render($diff) { $xi = $yi = 1; $block = false; $context = array(); $nlead = $this->_leading_context_lines; $ntrail = $this->_trailing_context_lines; $output = $this->_startDiff(); $diffs = $diff->getDiff(); foreach ($diffs as $i => $edit) { /* If these are unchanged (copied) lines, and we want to keep * leading or trailing context lines, extract them from the copy * block. */ if (is_a($edit, 'Text_Diff_Op_copy')) { /* Do we have any diff blocks yet? */ if (is_array($block)) { /* How many lines to keep as context from the copy * block. */ $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail; if (count($edit->orig) <= $keep) { /* We have less lines in the block than we want for * context => keep the whole block. */ $block[] = $edit; } else { if ($ntrail) { /* Create a new block with as many lines as we need * for the trailing context. */ $context = array_slice($edit->orig, 0, $ntrail); $block[] = new Text_Diff_Op_copy($context); } /* @todo */ $output .= $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block); $block = false; } } /* Keep the copy block as the context for the next block. */ $context = $edit->orig; } else { /* Don't we have any diff blocks yet? */ if (!is_array($block)) { /* Extract context lines from the preceding copy block. */ $context = array_slice($context, count($context) - $nlead); $x0 = $xi - count($context); $y0 = $yi - count($context); $block = array(); if ($context) { $block[] = new Text_Diff_Op_copy($context); } } $block[] = $edit; } if ($edit->orig) { $xi += count($edit->orig); } if ($edit->final) { $yi += count($edit->final); } } if (is_array($block)) { $output .= $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block); } return $output . $this->_endDiff(); }
/** * Returns the array of differences. * * @param array $from_lines lines of text from old file * @param array $to_lines lines of text from new file * * @return array all changes made (array with Text_Diff_Op_* objects) */ function diff($from_lines, $to_lines) { array_walk($from_lines, array('Text_Diff', 'trimNewlines')); array_walk($to_lines, array('Text_Diff', 'trimNewlines')); $temp_dir = Text_Diff::_getTempDir(); // Execute gnu diff or similar to get a standard diff file. $from_file = tempnam($temp_dir, 'Text_Diff'); $to_file = tempnam($temp_dir, 'Text_Diff'); $fp = fopen($from_file, 'w'); fwrite($fp, implode("\n", $from_lines)); fclose($fp); $fp = fopen($to_file, 'w'); fwrite($fp, implode("\n", $to_lines)); fclose($fp); $diff = shell_exec($this->_diffCommand . ' ' . $from_file . ' ' . $to_file); unlink($from_file); unlink($to_file); if (is_null($diff)) { // No changes were made return array(new Text_Diff_Op_copy($from_lines)); } $from_line_no = 1; $to_line_no = 1; $edits = array(); // Get changed lines by parsing something like: // 0a1,2 // 1,2c4,6 // 1,5d6 preg_match_all('#^(\\d+)(?:,(\\d+))?([adc])(\\d+)(?:,(\\d+))?$#m', $diff, $matches, PREG_SET_ORDER); foreach ($matches as $match) { if (!isset($match[5])) { // This paren is not set every time (see regex). $match[5] = false; } if ($match[3] == 'a') { $from_line_no--; } if ($match[3] == 'd') { $to_line_no--; } if ($from_line_no < $match[1] || $to_line_no < $match[4]) { // copied lines assert('$match[1] - $from_line_no == $match[4] - $to_line_no'); array_push($edits, new Text_Diff_Op_copy($this->_getLines($from_lines, $from_line_no, $match[1] - 1), $this->_getLines($to_lines, $to_line_no, $match[4] - 1))); } switch ($match[3]) { case 'd': // deleted lines array_push($edits, new Text_Diff_Op_delete($this->_getLines($from_lines, $from_line_no, $match[2]))); $to_line_no++; break; case 'c': // changed lines array_push($edits, new Text_Diff_Op_change($this->_getLines($from_lines, $from_line_no, $match[2]), $this->_getLines($to_lines, $to_line_no, $match[5]))); break; case 'a': // added lines array_push($edits, new Text_Diff_Op_add($this->_getLines($to_lines, $to_line_no, $match[5]))); $from_line_no++; break; } } if (!empty($from_lines)) { // Some lines might still be pending. Add them as copied array_push($edits, new Text_Diff_Op_copy($this->_getLines($from_lines, $from_line_no, $from_line_no + count($from_lines) - 1), $this->_getLines($to_lines, $to_line_no, $to_line_no + count($to_lines) - 1))); } return $edits; }
function check_filterless_things() { // Var is string with length 113: /wp-admin/plugin-editor.php?file=my-plugin%2Fviews%2Fplugin-file.php $referer = wp_get_referer(); // contains key "path" with value like "/wp-admin/plugin-editor.php" $referer_info = parse_url($referer); if ("/wp-admin/plugin-editor.php" === $referer_info["path"]) { // We are in plugin editor // Check for plugin edit saved if (isset($_POST["newcontent"]) && isset($_POST["action"]) && "update" == $_POST["action"] && isset($_POST["file"]) && !empty($_POST["file"])) { // A file was edited $file = $_POST["file"]; // $plugins = get_plugins(); // http://codex.wordpress.org/Function_Reference/wp_text_diff // Generate a diff of changes if (!class_exists('WP_Text_Diff_Renderer_Table')) { require_once ABSPATH . WPINC . '/wp-diff.php'; } $original_file_contents = file_get_contents(WP_PLUGIN_DIR . "/" . $file); $new_file_contents = wp_unslash($_POST["newcontent"]); $left_lines = explode("\n", $original_file_contents); $right_lines = explode("\n", $new_file_contents); $text_diff = new Text_Diff($left_lines, $right_lines); $num_added_lines = $text_diff->countAddedLines(); $num_removed_lines = $text_diff->countDeletedLines(); // Generate a diff in classic diff format $renderer = new Text_Diff_Renderer(); $diff = $renderer->render($text_diff); $this->infoMessage('plugin_file_edited', array("plugin_edited_file" => $file, "plugin_edit_diff" => $diff, "plugin_edit_num_added_lines" => $num_added_lines, "plugin_edit_num_removed_lines" => $num_removed_lines)); $did_log = true; } } }
function diffChar($orig, $final, $words = 0, $function = 'character') { $glue = strpos($function, 'inline') !== false ? "<br />" : "\n"; if ($words) { preg_match_all("/\\w+\\s+(?=\\w)|\\w+|\\W/u", implode($glue, $orig), $matches); $line1 = $matches[0]; preg_match_all("/\\w+\\s+(?=\\w)|\\w+|\\W/u", implode($glue, $final), $matches); $line2 = $matches[0]; } else { $line1 = preg_split('//u', implode($glue, $orig), -1, PREG_SPLIT_NO_EMPTY); $line2 = preg_split('//u', implode($glue, $final), -1, PREG_SPLIT_NO_EMPTY); } $z = new Text_Diff($line1, $line2); if ($z->isEmpty()) { return array($orig[0], $final[0]); } //echo "<pre>";print_r($z);echo "</pre>"; compileRendererClass($function); $new = "Text_Diff_Renderer_{$function}"; $renderer = new $new(count($line1)); return $renderer->render($z); }
function diff_sheets_as_html($id, $dates = null) { global $prefs, $sheetlib; function count_longest($array1, $array2) { return count($array1) > count($array2) ? count($array1) : count($array2); } function join_with_sub_grids($id, $date) { global $prefs, $sheetlib; $result1 = ""; $result2 = ""; $handler = new TikiSheetDatabaseHandler($id, $date); $handler->setReadDate($date); $grid = new TikiSheet(); $grid->import($handler); $childSheetIds = $sheetlib->get_related_sheet_ids($grid->id); $i = 0; $grids = array($grid); foreach ($childSheetIds as $childSheetId) { $handler = new TikiSheetDatabaseHandler($childSheetId, $date); $handler->setReadDate($date); $childSheet = new TikiSheet(); $childSheet->import($handler); array_push($grids, $childSheet); $i++; } return $grids; } function sanitize_for_diff($val) { $val = str_replace("<br/>", "<br>", $val); $val = str_replace("<br />", "<br>", $val); $val = str_replace("<br />", "<br>", $val); $val = str_replace("<BR/>", "<br>", $val); $val = str_replace("<BR />", "<br>", $val); $val = str_replace("<BR />", "<br>", $val); return explode("<br>", $val); } function diff_to_html($changes) { $result = array("", ""); for ($i = 0; $i < count_longest($changes->orig, $changes->final); $i++) { $class = array("", ""); $char = array("", ""); $vals = array(trim($changes->orig[$i]), trim($changes->final[$i])); if ($vals[0] && $vals[1]) { if ($vals[0] != $vals[1]) { $class[1] .= "diffadded"; } } else { if ($vals[0]) { $class[0] .= "diffadded"; $class[1] .= "diffdeleted"; $vals[1] = $vals[0]; $char[1] = "-"; } else { if ($vals[1]) { $class[0] .= "diffdeleted"; $class[1] .= "diffadded"; $char[1] = "+"; } } } if ($vals[0]) { $result[0] .= "<td class='{$class['0']}'>" . $char[0] . $vals[0] . "</td>"; } if ($vals[1]) { $result[1] .= "<td class='{$class['1']}'>" . $char[1] . $vals[1] . "</td>"; } } return $result; } $grids1 = join_with_sub_grids($id, $dates[0]); $grids2 = join_with_sub_grids($id, $dates[1]); for ($i = 0; $i < count_longest($grids1, $grids2); $i++) { //cycle through the sheets within a spreadsheet $result1 .= "<table title='" . $grids1[$i]->name() . "'>"; $result2 .= "<table title='" . $grids2[$i]->name() . "'>"; for ($row = 0; $row < count_longest($grids1[$i]->dataGrid, $grids2[$i]->dataGrid); $row++) { //cycle through rows $result1 .= "<tr>"; $result2 .= "<tr>"; for ($col = 0; $col < count_longest($grids1[$i]->dataGrid[$row], $grids2[$i]->dataGrid[$row]); $col++) { //cycle through columns $diff = new Text_Diff(sanitize_for_diff($grids1[$i]->dataGrid[$row][$col]), sanitize_for_diff($grids2[$i]->dataGrid[$row][$col])); $changes = $diff->getDiff(); //print_r($changes); $class = array('', ''); $values = array('', ''); //I left this diff switch, but it really isn't being used as of now, in the future we may though. switch (get_class($changes[0])) { case 'Text_Diff_Op_copy': $values = diff_to_html($changes[0]); break; case 'Text_Diff_Op_change': $values = diff_to_html($changes[0]); break; case 'Text_Diff_Op_delete': $values = diff_to_html($changes[0]); break; case 'Text_Diff_Op_add': $values = diff_to_html($changes[0]); break; default: $values = diff_to_html($changes[0]); } $result1 .= empty($values[0]) ? '<td></td>' : $values[0]; $result2 .= empty($values[1]) ? '<td></td>' : $values[1]; } $result1 .= "</tr>"; $result2 .= "</tr>"; } $result1 .= "</table>"; $result2 .= "</table>"; } return array($result1, $result2); }
/** * * merges a newer version of a page into the current document * @param string $newpage a string with a later version of the page * @param string $newauthor name of the author of the new version */ function mergeDiff($newpage, $newauthor) { global $tikilib; $this->_history=false; $author=$newauthor; $deleted=false; $deleted_by=''; $newdoc=array(); $page=preg_replace(array('/\{AUTHOR\(.+?\)\}/','/{AUTHOR\}/','/\{INCLUDE\(.+?\)\}\{INCLUDE\}/'), ' ~np~$0~/np~', $newpage); if ($this->_parsed) { $page=$tikilib->parse_data($page, array('suppress_icons'=>true)); $page=preg_replace(array('/\{AUTHOR\(.+?\)\}/','/{AUTHOR\}/','/\{INCLUDE\(.+?\)\}\{INCLUDE\}/'), ' ~np~$0~/np~', $page); } if ($this->_nohtml) { $page=strip_tags($page); } preg_match_all($this->_search, $page, $out, PREG_PATTERN_ORDER); $new=$out[0]; $z = new Text_Diff($this->getDiffArray(), $new); $pos=0; foreach ($z->getDiff() as $element) { if (is_a($element, 'Text_Diff_Op_copy')) { $this->moveWords($newdoc, $pos, $element->orig, $deleted, $deleted_by); } else { if (is_a($element, 'Text_Diff_Op_add')) { $newdoc=$this->addWords($newdoc, $element->final, $author, $deleted, $deleted_by); } else { if (is_a($element, 'Text_Diff_Op_delete')) { $this->moveWords($newdoc, $pos, $element->orig, $deleted, $author); } else { //change $newdoc=$this->addWords($newdoc, $element->final, $author, $deleted, $deleted_by); $this->moveWords($newdoc, $pos, $element->orig, true, $author); } //delete } // add } // copy } // foreach diff $this->_document=$newdoc; }
/** * Text_MappedDiff constructor. * @param string $from_lines * @param array $to_lines * @param $mapped_from_lines * @param $mapped_to_lines */ public function __construct($from_lines, $to_lines, $mapped_from_lines, $mapped_to_lines) { assert(count($from_lines) == count($mapped_from_lines)); assert(count($to_lines) == count($mapped_to_lines)); parent::__construct($mapped_from_lines, $mapped_to_lines); $this->Text_MappedDiff($from_lines, $to_lines, $mapped_from_lines, $mapped_to_lines); }
$fragments = array(); $start = $end = 0; for (;;) { $end += strcspn($text, $delimiter, $end); $end += strspn($text, $delimiter, $end); if ($end === $start) { break; } $fragments[] = substr($text, $start, $end - $start); $start = $end; } return $fragments; } $from_fragments = extractFragments($from, $delimiters[$granularity]); $to_fragments = extractFragments($to, $delimiters[$granularity]); $diff = new Text_Diff('native', array($from_fragments, $to_fragments)); $exec_time = sprintf('%.3f sec', gettimeofday(true) - $start_time); $edits = array(); ob_start(); foreach ($diff->getDiff() as $edit) { if ($edit instanceof Text_Diff_Op_copy) { $orig = str_replace(array("", ""), array("\n", "\r"), implode('', $edit->orig)); $edits[] = new fineDiffCopyOp(strlen($orig)); echo htmlentities($orig); } else { if ($edit instanceof Text_Diff_Op_delete) { $orig = str_replace(array("", ""), array("\n", "\r"), implode('', $edit->orig)); $edits[] = new fineDiffDeleteOp(strlen($orig)); echo '<del>', htmlentities($orig), '</del>'; } else { if ($edit instanceof Text_Diff_Op_add) {
function diffLatestWithArchive($archive = 0) { include_once "lib/diff/Diff.php"; $textDiff = new Text_Diff(FileGallery_File::id($this->getParam('fileId'))->archive($archive)->data(), $this->data()); return $textDiff->getDiff(); }
/** * Displays a human readable HTML representation of the difference between two strings. * similar to wp_text_diff, but tracks and returns could of lines added and removed * * @since 3.6.0 * * @see wp_parse_args() Used to change defaults to user defined settings. * @uses Text_Diff * @uses WP_Text_Diff_Renderer_Table * * @param string $left_string "old" (left) version of string * @param string $right_string "new" (right) version of string * @param string|array $args Optional. Change 'title', 'title_left', and 'title_right' defaults. * @return array contains html, linesadded & linesdeletd, empty string if strings are equivalent. */ function wp_text_diff_with_count($left_string, $right_string, $args = null) { $defaults = array('title' => '', 'title_left' => '', 'title_right' => ''); $args = wp_parse_args($args, $defaults); if (!class_exists('WP_Text_Diff_Renderer_Table')) { require ABSPATH . WPINC . '/wp-diff.php'; } $left_string = normalize_whitespace($left_string); $right_string = normalize_whitespace($right_string); $left_lines = explode("\n", $left_string); $right_lines = explode("\n", $right_string); $text_diff = new Text_Diff($left_lines, $right_lines); $lines_added = $text_diff->countAddedLines(); $lines_deleted = $text_diff->countDeletedLines(); $renderer = new WP_Text_Diff_Renderer_Table(); $diff = $renderer->render($text_diff); if (!$diff) { return ''; } $r = "<table class='diff'>\n"; if (!empty($args['show_split_view'])) { $r .= "<col class='content diffsplit left' /><col class='content diffsplit middle' /><col class='content diffsplit right' />"; } else { $r .= "<col class='content' />"; } if ($args['title'] || $args['title_left'] || $args['title_right']) { $r .= "<thead>"; } if ($args['title']) { $r .= "<tr class='diff-title'><th colspan='4'>{$args['title']}</th></tr>\n"; } if ($args['title_left'] || $args['title_right']) { $r .= "<tr class='diff-sub-title'>\n"; $r .= "\t<td></td><th>{$args['title_left']}</th>\n"; $r .= "\t<td></td><th>{$args['title_right']}</th>\n"; $r .= "</tr>\n"; } if ($args['title'] || $args['title_left'] || $args['title_right']) { $r .= "</thead>\n"; } $r .= "<tbody>\n{$diff}\n</tbody>\n"; $r .= "</table>"; return array('html' => $r, 'lines_added' => $lines_added, 'lines_deleted' => $lines_deleted); }
function diffChar($orig, $final) { $line1 = preg_split('//', implode("<br />", $orig), -1, PREG_SPLIT_NO_EMPTY); $line2 = preg_split('//', implode("<br />", $final), -1, PREG_SPLIT_NO_EMPTY); $z = new Text_Diff($line1, $line2); if ($z->isEmpty()) { return array($orig[0], $final[0]); } // echo "<pre>";print_r($z);echo "</pre>"; require_once 'character.php'; $renderer = new Text_Diff_Renderer_character(10000); return $renderer->render($z); }
/** * Get a html diff between two versions. * * @param string latest_revision id of the latest revision * @param string oldest_revision id of the oldest revision * @return array array with the original value, the new value and a diff -u */ public function get_diff($oldest_revision, $latest_revision, $renderer_style = 'inline') { if (!class_exists('Text_Diff')) { @(include_once 'Text/Diff.php'); @(include_once 'Text/Diff/Renderer.php'); @(include_once 'Text/Diff/Renderer/unified.php'); @(include_once 'Text/Diff/Renderer/inline.php'); if (!class_exists('Text_Diff')) { throw new midcom_error("Failed to load Text_Diff library."); } } $oldest = $this->get_revision($oldest_revision); $newest = $this->get_revision($latest_revision); $return = array(); foreach ($oldest as $attribute => $oldest_value) { if (!array_key_exists($attribute, $newest)) { continue; // This isn't in the newer version, skip } if (is_array($oldest_value)) { continue; // Skip } $return[$attribute] = array('old' => $oldest_value, 'new' => $newest[$attribute]); if ($oldest_value != $newest[$attribute]) { $lines1 = explode("\n", $oldest_value); $lines2 = explode("\n", $newest[$attribute]); $diff = new Text_Diff($lines1, $lines2); if ($renderer_style == 'unified') { $renderer = new Text_Diff_Renderer_unified(); } else { $renderer = new Text_Diff_Renderer_inline(); } if (!$diff->isEmpty()) { // Run the diff $return[$attribute]['diff'] = $renderer->render($diff); if ($renderer_style == 'inline') { // Modify the output for nicer rendering $return[$attribute]['diff'] = str_replace('<del>', "<span class=\"deleted\" title=\"removed in {$latest_revision}\">", $return[$attribute]['diff']); $return[$attribute]['diff'] = str_replace('</del>', '</span>', $return[$attribute]['diff']); $return[$attribute]['diff'] = str_replace('<ins>', "<span class=\"inserted\" title=\"added in {$latest_revision}\">", $return[$attribute]['diff']); $return[$attribute]['diff'] = str_replace('</ins>', '</span>', $return[$attribute]['diff']); } } } } return $return; }
/** * Computes a diff between sequences of strings. * * This can be used to compute things like case-insensitve diffs, or diffs * which ignore changes in white-space. * * @param array $from_lines An array of strings. * @param array $to_lines An array of strings. * @param array $mapped_from_lines This array should have the same size * number of elements as $from_lines. The * elements in $mapped_from_lines and * $mapped_to_lines are what is actually * compared when computing the diff. * @param array $mapped_to_lines This array should have the same number * of elements as $to_lines. */ function __construct($from_lines, $to_lines, $mapped_from_lines, $mapped_to_lines) { // assert(count($from_lines) == count($mapped_from_lines)); // assert(count($to_lines) == count($mapped_to_lines)); parent::__construct($mapped_from_lines, $mapped_to_lines); $xi = $yi = 0; for ($i = 0, $count_edits = count($this->edits); $i < $count_edits; $i++) { $orig =& $this->edits[$i]->orig; if (is_array($orig)) { $orig = array_slice($from_lines, $xi, count($orig)); $xi += count($orig); } $final =& $this->edits[$i]->final; if (is_array($final)) { $final = array_slice($to_lines, $yi, count($final)); $yi += count($final); } } }
function diffChar($orig, $final, $words = 0, $function = 'character') { if ($words) { preg_match_all("/\\w+\\s+(?=\\w)|\\w+|\\W/", implode("<br />", $orig), $matches); $line1 = $matches[0]; preg_match_all("/\\w+\\s+(?=\\w)|\\w+|\\W/", implode("<br />", $final), $matches); $line2 = $matches[0]; } else { $line1 = preg_split('//', implode("<br />", $orig), -1, PREG_SPLIT_NO_EMPTY); $line2 = preg_split('//', implode("<br />", $final), -1, PREG_SPLIT_NO_EMPTY); } $z = new Text_Diff($line1, $line2); if ($z->isEmpty()) { return array($orig[0], $final[0]); } //echo "<pre>";print_r($z);echo "</pre>"; require_once "renderer_{$function}.php"; $new = "Text_Diff_Renderer_{$function}"; $renderer = new $new(sizeof($line1)); return $renderer->render($z); }
/** * Get the difference between original text and a changed body of text * * @param string The old text * @param string The changed text * @return array */ public static function get_text_diff($old_content, $new_content) { $old_file = explode("\n", $old_content); $new_file = explode("\n", $new_content); $diff = new Text_Diff('auto', array($old_file, $new_file)); $added = $diff->countAddedLines(); $deleted = $diff->countDeletedLines(); if ($added == 0 && $deleted == 0) { return false; } $net = $added - $deleted; $result = array(); $result_added = 0; $result_changed = 0; $result_deleted = 0; if ($net == 0) { $result_changed = $added; } elseif ($net > 0) { $result_changed = $added - $net; $result_added = $net; } elseif ($net < 0) { $result_changed = $deleted - abs($net); $result_deleted = abs($net); } return array('added' => $result_added, 'deleted' => $result_deleted, 'changed' => $result_changed); }