From 96fcbd972bb9e1bfb1398da14539dee447a20e7d Mon Sep 17 00:00:00 2001 From: Meik Sievertsen Date: Sun, 7 Jun 2009 18:00:37 +0000 Subject: moved diff git-svn-id: file:///svn/phpbb/trunk@9556 89ea8834-ac86-4346-8a33-228a782c2dd0 --- phpBB/includes/diff/renderer.php | 858 --------------------------------------- 1 file changed, 858 deletions(-) delete mode 100644 phpBB/includes/diff/renderer.php (limited to 'phpBB/includes/diff/renderer.php') diff --git a/phpBB/includes/diff/renderer.php b/phpBB/includes/diff/renderer.php deleted file mode 100644 index 2d3ab88a26..0000000000 --- a/phpBB/includes/diff/renderer.php +++ /dev/null @@ -1,858 +0,0 @@ - $value) - { - $v = '_' . $param; - if (isset($this->$v)) - { - $this->$v = $value; - } - } - } - - /** - * Get any renderer parameters. - * - * @return array All parameters of this renderer object. - */ - function get_params() - { - $params = array(); - foreach (get_object_vars($this) as $k => $v) - { - if ($k[0] == '_') - { - $params[substr($k, 1)] = $v; - } - } - - return $params; - } - - /** - * Renders a diff. - * - * @param diff &$diff A diff object. - * - * @return string The formatted output. - */ - function render(&$diff) - { - $xi = $yi = 1; - $block = false; - $context = array(); - - // Create a new diff object if it is a 3-way diff - if (is_a($diff, 'diff3')) - { - $diff3 = &$diff; - - $diff_1 = $diff3->get_original(); - $diff_2 = $diff3->merged_output(); - - unset($diff3); - - $diff = new diff($diff_1, $diff_2); - } - - $nlead = $this->_leading_context_lines; - $ntrail = $this->_trailing_context_lines; - - $output = $this->_start_diff(); - $diffs = $diff->get_diff(); - - 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, '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 == sizeof($diffs) - 1) ? $ntrail : $nlead + $ntrail; - if (sizeof($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 diff_op_copy($context); - } - - $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, sizeof($context) - $nlead); - $x0 = $xi - sizeof($context); - $y0 = $yi - sizeof($context); - $block = array(); - - if ($context) - { - $block[] = new diff_op_copy($context); - } - } - $block[] = $edit; - } - - $xi += ($edit->orig) ? sizeof($edit->orig) : 0; - $yi += ($edit->final) ? sizeof($edit->final) : 0; - } - - if (is_array($block)) - { - $output .= $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block); - } - - return $output . $this->_end_diff(); - } - - function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) - { - $output = $this->_start_block($this->_block_header($xbeg, $xlen, $ybeg, $ylen)); - - foreach ($edits as $edit) - { - switch (get_class($edit)) - { - case 'diff_op_copy': - $output .= $this->_context($edit->orig); - break; - - case 'diff_op_add': - $output .= $this->_added($edit->final); - break; - - case 'diff_op_delete': - $output .= $this->_deleted($edit->orig); - break; - - case 'diff_op_change': - $output .= $this->_changed($edit->orig, $edit->final); - break; - } - } - - return $output . $this->_end_block(); - } - - function _start_diff() - { - return ''; - } - - function _end_diff() - { - return ''; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen > 1) - { - $xbeg .= ',' . ($xbeg + $xlen - 1); - } - - if ($ylen > 1) - { - $ybeg .= ',' . ($ybeg + $ylen - 1); - } - - // this matches the GNU Diff behaviour - if ($xlen && !$ylen) - { - $ybeg--; - } - else if (!$xlen) - { - $xbeg--; - } - - return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg; - } - - function _start_block($header) - { - return $header . "\n"; - } - - function _end_block() - { - return ''; - } - - function _lines($lines, $prefix = ' ') - { - return $prefix . implode("\n$prefix", $lines) . "\n"; - } - - function _context($lines) - { - return $this->_lines($lines, ' '); - } - - function _added($lines) - { - return $this->_lines($lines, '> '); - } - - function _deleted($lines) - { - return $this->_lines($lines, '< '); - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . "---\n" . $this->_added($final); - } - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return $this->render($diff); - } -} - -/** -* Renders a unified diff -* @package diff -*/ -class diff_renderer_unified extends diff_renderer -{ - var $_leading_context_lines = 4; - var $_trailing_context_lines = 4; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return nl2br($this->render($diff)); - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen != 1) - { - $xbeg .= ',' . $xlen; - } - - if ($ylen != 1) - { - $ybeg .= ',' . $ylen; - } - return '
@@ -' . $xbeg . ' +' . $ybeg . ' @@
'; - } - - function _context($lines) - { - return '
' . htmlspecialchars($this->_lines($lines, ' ')) . '
'; - } - - function _added($lines) - { - return '
' . htmlspecialchars($this->_lines($lines, '+')) . '
'; - } - - function _deleted($lines) - { - return '
' . htmlspecialchars($this->_lines($lines, '-')) . '
'; - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . $this->_added($final); - } - - function _start_diff() - { - $start = '
'; - - return $start; - } - - function _end_diff() - { - return '
'; - } - - function _end_block() - { - return ''; - } -} - -/** -* "Inline" diff renderer. -* -* This class renders diffs in the Wiki-style "inline" format. -* -* @author Ciprian Popovici -* @package diff -*/ -class diff_renderer_inline extends diff_renderer -{ - var $_leading_context_lines = 10000; - var $_trailing_context_lines = 10000; - - // Prefix and suffix for inserted text - var $_ins_prefix = ''; - var $_ins_suffix = ''; - - // Prefix and suffix for deleted text - var $_del_prefix = ''; - var $_del_suffix = ''; - - var $_block_head = ''; - - // What are we currently splitting on? Used to recurse to show word-level - var $_split_level = 'lines'; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return '
' . nl2br($this->render($diff)) . '
'; - } - - function _start_diff() - { - return ''; - } - - function _end_diff() - { - return ''; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - return $this->_block_head; - } - - function _start_block($header) - { - return $header; - } - - function _lines($lines, $prefix = ' ', $encode = true) - { - if ($encode) - { - array_walk($lines, array(&$this, '_encode')); - } - - if ($this->_split_level == 'words') - { - return implode('', $lines); - } - else - { - return implode("\n", $lines) . "\n"; - } - } - - function _added($lines) - { - array_walk($lines, array(&$this, '_encode')); - $lines[0] = $this->_ins_prefix . $lines[0]; - $lines[sizeof($lines) - 1] .= $this->_ins_suffix; - return $this->_lines($lines, ' ', false); - } - - function _deleted($lines, $words = false) - { - array_walk($lines, array(&$this, '_encode')); - $lines[0] = $this->_del_prefix . $lines[0]; - $lines[sizeof($lines) - 1] .= $this->_del_suffix; - return $this->_lines($lines, ' ', false); - } - - function _changed($orig, $final) - { - // If we've already split on words, don't try to do so again - just display. - if ($this->_split_level == 'words') - { - $prefix = ''; - while ($orig[0] !== false && $final[0] !== false && substr($orig[0], 0, 1) == ' ' && substr($final[0], 0, 1) == ' ') - { - $prefix .= substr($orig[0], 0, 1); - $orig[0] = substr($orig[0], 1); - $final[0] = substr($final[0], 1); - } - - return $prefix . $this->_deleted($orig) . $this->_added($final); - } - - $text1 = implode("\n", $orig); - $text2 = implode("\n", $final); - - // Non-printing newline marker. - $nl = "\0"; - - // We want to split on word boundaries, but we need to preserve whitespace as well. - // Therefore we split on words, but include all blocks of whitespace in the wordlist. - $splitted_text_1 = $this->_split_on_words($text1, $nl); - $splitted_text_2 = $this->_split_on_words($text2, $nl); - - $diff = new diff($splitted_text_1, $splitted_text_2); - unset($splitted_text_1, $splitted_text_2); - - // Get the diff in inline format. - $renderer = new diff_renderer_inline(array_merge($this->get_params(), array('split_level' => 'words'))); - - // Run the diff and get the output. - return str_replace($nl, "\n", $renderer->render($diff)) . "\n"; - } - - function _split_on_words($string, $newline_escape = "\n") - { - // Ignore \0; otherwise the while loop will never finish. - $string = str_replace("\0", '', $string); - - $words = array(); - $length = strlen($string); - $pos = 0; - - $tab_there = true; - while ($pos < $length) - { - // Check for tabs... do not include them - if ($tab_there && substr($string, $pos, 1) === "\t") - { - $words[] = "\t"; - $pos++; - - continue; - } - else - { - $tab_there = false; - } - - // Eat a word with any preceding whitespace. - $spaces = strspn(substr($string, $pos), " \n"); - $nextpos = strcspn(substr($string, $pos + $spaces), " \n"); - $words[] = str_replace("\n", $newline_escape, substr($string, $pos, $spaces + $nextpos)); - $pos += $spaces + $nextpos; - } - - return $words; - } - - function _encode(&$string) - { - $string = htmlspecialchars($string); - } -} - -/** -* "raw" diff renderer. -* This class could be used to output a raw unified patch file -* -* @package diff -*/ -class diff_renderer_raw extends diff_renderer -{ - var $_leading_context_lines = 4; - var $_trailing_context_lines = 4; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return ''; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen != 1) - { - $xbeg .= ',' . $xlen; - } - - if ($ylen != 1) - { - $ybeg .= ',' . $ylen; - } - return '@@ -' . $xbeg . ' +' . $ybeg . ' @@'; - } - - function _context($lines) - { - return $this->_lines($lines, ' '); - } - - function _added($lines) - { - return $this->_lines($lines, '+'); - } - - function _deleted($lines) - { - return $this->_lines($lines, '-'); - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . $this->_added($final); - } -} - -/** -* "chora (Horde)" diff renderer - similar style. -* This renderer class is a modified human_readable function from the Horde Framework. -* -* @package diff -*/ -class diff_renderer_side_by_side extends diff_renderer -{ - var $_leading_context_lines = 3; - var $_trailing_context_lines = 3; - - var $lines = array(); - - // Hold the left and right columns of lines for change blocks. - var $cols; - var $state; - - var $data = false; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - $output = ''; - $output .= ' - - -'; - - $this->render($diff); - - // Is the diff empty? - if (!sizeof($this->lines)) - { - $output .= ''; - } - else - { - // Iterate through every header block of changes - foreach ($this->lines as $header) - { - $output .= ''; - - // Each header block consists of a number of changes (add, remove, change). - $current_context = ''; - - foreach ($header['contents'] as $change) - { - if (!empty($current_context) && $change['type'] != 'empty') - { - $line = $current_context; - $current_context = ''; - - $output .= ' - '; - } - - switch ($change['type']) - { - case 'add': - $line = ''; - - foreach ($change['lines'] as $_line) - { - $line .= htmlspecialchars($_line) . '
'; - } - - $output .= ''; - break; - - case 'remove': - $line = ''; - - foreach ($change['lines'] as $_line) - { - $line .= htmlspecialchars($_line) . '
'; - } - - $output .= ''; - break; - - case 'empty': - $current_context .= htmlspecialchars($change['line']) . '
'; - break; - - case 'change': - // Pop the old/new stacks one by one, until both are empty. - $oldsize = sizeof($change['old']); - $newsize = sizeof($change['new']); - $left = $right = ''; - - for ($row = 0, $row_max = max($oldsize, $newsize); $row < $row_max; ++$row) - { - $left .= isset($change['old'][$row]) ? htmlspecialchars($change['old'][$row]) : ''; - $left .= '
'; - $right .= isset($change['new'][$row]) ? htmlspecialchars($change['new'][$row]) : ''; - $right .= '
'; - } - - $output .= ''; - - if (!empty($left)) - { - $output .= ''; - } - else if ($row < $oldsize) - { - $output .= ''; - } - else - { - $output .= ''; - } - - if (!empty($right)) - { - $output .= ''; - } - else if ($row < $newsize) - { - $output .= ''; - } - else - { - $output .= ''; - } - - $output .= ''; - break; - } - } - - if (!empty($current_context)) - { - $line = $current_context; - $current_context = ''; - - $output .= ''; - $output .= ''; - } - } - } - - $output .= '
-   ' . phpbb::$user->lang['LINE_UNMODIFIED'] . ' -   ' . phpbb::$user->lang['LINE_ADDED'] . ' -   ' . phpbb::$user->lang['LINE_MODIFIED'] . ' -   ' . phpbb::$user->lang['LINE_REMOVED'] . ' -
' . phpbb::$user->lang['NO_VISIBLE_CHANGES'] . '
' . phpbb::$user->lang['LINE'] . ' ' . $header['oldline'] . '' . phpbb::$user->lang['LINE'] . ' ' . $header['newline'] . '
' . ((strlen($line)) ? $line : ' ') . '
' . ((strlen($line)) ? $line : ' ') . '
 
' . ((strlen($line)) ? $line : ' ') . '
' . ((strlen($line)) ? $line : ' ') . '
 
' . $left . '
  
' . $right . '
  
' . ((strlen($line)) ? $line : ' ') . '
' . ((strlen($line)) ? $line : ' ') . '
'; - - return $output; - } - - function _start_diff() - { - $this->lines = array(); - - $this->data = false; - $this->cols = array(array(), array()); - $this->state = 'empty'; - - return ''; - } - - function _end_diff() - { - // Just flush any remaining entries in the columns stack. - switch ($this->state) - { - case 'add': - $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]); - break; - - case 'remove': - // We have some removal lines pending in our stack, so flush them. - $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]); - break; - - case 'change': - // We have both remove and addition lines, so this is a change block. - $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]); - break; - } - - if ($this->data !== false) - { - $this->lines[] = $this->data; - } - - return ''; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - // Push any previous header information to the return stack. - if ($this->data !== false) - { - $this->lines[] = $this->data; - } - - $this->data = array('type' => 'header', 'oldline' => $xbeg, 'newline' => $ybeg, 'contents' => array()); - $this->state = 'dump'; - } - - function _added($lines) - { - array_walk($lines, array(&$this, '_perform_add')); - } - - function _perform_add($line) - { - if ($this->state == 'empty') - { - return ''; - } - - // This is just an addition line. - if ($this->state == 'dump' || $this->state == 'add') - { - // Start adding to the addition stack. - $this->cols[0][] = $line; - $this->state = 'add'; - } - else - { - // This is inside a change block, so start accumulating lines. - $this->state = 'change'; - $this->cols[1][] = $line; - } - } - - function _deleted($lines) - { - array_walk($lines, array(&$this, '_perform_delete')); - } - - function _perform_delete($line) - { - // This is a removal line. - $this->state = 'remove'; - $this->cols[0][] = $line; - } - - function _context($lines) - { - array_walk($lines, array(&$this, '_perform_context')); - } - - function _perform_context($line) - { - // An empty block with no action. - switch ($this->state) - { - case 'add': - $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]); - break; - - case 'remove': - // We have some removal lines pending in our stack, so flush them. - $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]); - break; - - case 'change': - // We have both remove and addition lines, so this is a change block. - $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]); - break; - } - - $this->cols = array(array(), array()); - $this->data['contents'][] = array('type' => 'empty', 'line' => $line); - $this->state = 'dump'; - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . $this->_added($final); - } - -} - -?> \ No newline at end of file -- cgit v1.2.1