/wp-includes/Text/Diff/Renderer.php

  1. <?php 
  2. /** 
  3. * A class to render Diffs in different formats. 
  4. * 
  5. * This class renders the diff in classic diff format. It is intended that 
  6. * this class be customized via inheritance, to obtain fancier outputs. 
  7. * 
  8. * Copyright 2004-2010 The Horde Project (http://www.horde.org/) 
  9. * 
  10. * See the enclosed file COPYING for license information (LGPL). If you did 
  11. * not receive this file, see http://opensource.org/licenses/lgpl-license.php. 
  12. * 
  13. * @package Text_Diff 
  14. */ 
  15. class Text_Diff_Renderer { 
  16.  
  17. /** 
  18. * Number of leading context "lines" to preserve. 
  19. * 
  20. * This should be left at zero for this class, but subclasses may want to 
  21. * set this to other values. 
  22. */ 
  23. var $_leading_context_lines = 0; 
  24.  
  25. /** 
  26. * Number of trailing context "lines" to preserve. 
  27. * 
  28. * This should be left at zero for this class, but subclasses may want to 
  29. * set this to other values. 
  30. */ 
  31. var $_trailing_context_lines = 0; 
  32.  
  33. /** 
  34. * Constructor. 
  35. */ 
  36. function __construct( $params = array() ) 
  37. foreach ($params as $param => $value) { 
  38. $v = '_' . $param; 
  39. if (isset($this->$v)) { 
  40. $this->$v = $value; 
  41.  
  42. /** 
  43. * PHP4 constructor. 
  44. */ 
  45. public function Text_Diff_Renderer( $params = array() ) { 
  46. self::__construct( $params ); 
  47.  
  48. /** 
  49. * Get any renderer parameters. 
  50. * 
  51. * @return array All parameters of this renderer object. 
  52. */ 
  53. function getParams() 
  54. $params = array(); 
  55. foreach (get_object_vars($this) as $k => $v) { 
  56. if ($k[0] == '_') { 
  57. $params[substr($k, 1)] = $v; 
  58.  
  59. return $params; 
  60.  
  61. /** 
  62. * Renders a diff. 
  63. * 
  64. * @param Text_Diff $diff A Text_Diff object. 
  65. * 
  66. * @return string The formatted output. 
  67. */ 
  68. function render($diff) 
  69. $xi = $yi = 1; 
  70. $block = false; 
  71. $context = array(); 
  72.  
  73. $nlead = $this->_leading_context_lines; 
  74. $ntrail = $this->_trailing_context_lines; 
  75.  
  76. $output = $this->_startDiff(); 
  77.  
  78. $diffs = $diff->getDiff(); 
  79. foreach ($diffs as $i => $edit) { 
  80. /** If these are unchanged (copied) lines, and we want to keep 
  81. * leading or trailing context lines, extract them from the copy 
  82. * block. */ 
  83. if (is_a($edit, 'Text_Diff_Op_copy')) { 
  84. /** Do we have any diff blocks yet? */ 
  85. if (is_array($block)) { 
  86. /** How many lines to keep as context from the copy 
  87. * block. */ 
  88. $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail; 
  89. if (count($edit->orig) <= $keep) { 
  90. /** We have less lines in the block than we want for 
  91. * context => keep the whole block. */ 
  92. $block[] = $edit; 
  93. } else { 
  94. if ($ntrail) { 
  95. /** Create a new block with as many lines as we need 
  96. * for the trailing context. */ 
  97. $context = array_slice($edit->orig, 0, $ntrail); 
  98. $block[] = new Text_Diff_Op_copy($context); 
  99. /** @todo */ 
  100. $output .= $this->_block($x0, $ntrail + $xi - $x0,  
  101. $y0, $ntrail + $yi - $y0,  
  102. $block); 
  103. $block = false; 
  104. /** Keep the copy block as the context for the next block. */ 
  105. $context = $edit->orig; 
  106. } else { 
  107. /** Don't we have any diff blocks yet? */ 
  108. if (!is_array($block)) { 
  109. /** Extract context lines from the preceding copy block. */ 
  110. $context = array_slice($context, count($context) - $nlead); 
  111. $x0 = $xi - count($context); 
  112. $y0 = $yi - count($context); 
  113. $block = array(); 
  114. if ($context) { 
  115. $block[] = new Text_Diff_Op_copy($context); 
  116. $block[] = $edit; 
  117.  
  118. if ($edit->orig) { 
  119. $xi += count($edit->orig); 
  120. if ($edit->final) { 
  121. $yi += count($edit->final); 
  122.  
  123. if (is_array($block)) { 
  124. $output .= $this->_block($x0, $xi - $x0,  
  125. $y0, $yi - $y0,  
  126. $block); 
  127.  
  128. return $output . $this->_endDiff(); 
  129.  
  130. function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) 
  131. $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen)); 
  132.  
  133. foreach ($edits as $edit) { 
  134. switch (strtolower(get_class($edit))) { 
  135. case 'text_diff_op_copy': 
  136. $output .= $this->_context($edit->orig); 
  137. break; 
  138.  
  139. case 'text_diff_op_add': 
  140. $output .= $this->_added($edit->final); 
  141. break; 
  142.  
  143. case 'text_diff_op_delete': 
  144. $output .= $this->_deleted($edit->orig); 
  145. break; 
  146.  
  147. case 'text_diff_op_change': 
  148. $output .= $this->_changed($edit->orig, $edit->final); 
  149. break; 
  150.  
  151. return $output . $this->_endBlock(); 
  152.  
  153. function _startDiff() 
  154. return ''; 
  155.  
  156. function _endDiff() 
  157. return ''; 
  158.  
  159. function _blockHeader($xbeg, $xlen, $ybeg, $ylen) 
  160. if ($xlen > 1) { 
  161. $xbeg .= ', ' . ($xbeg + $xlen - 1); 
  162. if ($ylen > 1) { 
  163. $ybeg .= ', ' . ($ybeg + $ylen - 1); 
  164.  
  165. // this matches the GNU Diff behaviour 
  166. if ($xlen && !$ylen) { 
  167. $ybeg--; 
  168. } elseif (!$xlen) { 
  169. $xbeg--; 
  170.  
  171. return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg; 
  172.  
  173. function _startBlock($header) 
  174. return $header . "\n"; 
  175.  
  176. function _endBlock() 
  177. return ''; 
  178.  
  179. function _lines($lines, $prefix = ' ') 
  180. return $prefix . implode("\n$prefix", $lines) . "\n"; 
  181.  
  182. function _context($lines) 
  183. return $this->_lines($lines, ' '); 
  184.  
  185. function _added($lines) 
  186. return $this->_lines($lines, '> '); 
  187.  
  188. function _deleted($lines) 
  189. return $this->_lines($lines, '< '); 
  190.  
  191. function _changed($orig, $final) 
  192. return $this->_deleted($orig) . "---\n" . $this->_added($final); 
  193.  
.