includes/diffengine/Renderer.php
changeset 1227 bdac73ed481e
parent 1 fe660c52c48f
child 1383 198f5207119b
equal deleted inserted replaced
1226:de56132c008d 1227:bdac73ed481e
     9  *
     9  *
    10  * @package Text_Diff
    10  * @package Text_Diff
    11  */
    11  */
    12 class Text_Diff_Renderer {
    12 class Text_Diff_Renderer {
    13 
    13 
    14     /**
    14 		/**
    15      * Number of leading context "lines" to preserve.
    15  		* Number of leading context "lines" to preserve.
    16      *
    16  		*
    17      * This should be left at zero for this class, but subclasses may want to
    17  		* This should be left at zero for this class, but subclasses may want to
    18      * set this to other values.
    18  		* set this to other values.
    19      */
    19  		*/
    20     var $_leading_context_lines = 0;
    20 		var $_leading_context_lines = 0;
    21 
    21 
    22     /**
    22 		/**
    23      * Number of trailing context "lines" to preserve.
    23  		* Number of trailing context "lines" to preserve.
    24      *
    24  		*
    25      * This should be left at zero for this class, but subclasses may want to
    25  		* This should be left at zero for this class, but subclasses may want to
    26      * set this to other values.
    26  		* set this to other values.
    27      */
    27  		*/
    28     var $_trailing_context_lines = 0;
    28 		var $_trailing_context_lines = 0;
    29 
    29 
    30     /**
    30 		/**
    31      * Constructor.
    31  		* Constructor.
    32      */
    32  		*/
    33     function Text_Diff_Renderer($params = array())
    33 		function Text_Diff_Renderer($params = array())
    34     {
    34 		{
    35         foreach ($params as $param => $value) {
    35 				foreach ($params as $param => $value) {
    36             $v = '_' . $param;
    36 						$v = '_' . $param;
    37             if (isset($this->$v)) {
    37 						if (isset($this->$v)) {
    38                 $this->$v = $value;
    38 								$this->$v = $value;
    39             }
    39 						}
    40         }
    40 				}
    41     }
    41 		}
    42 
    42 
    43     /**
    43 		/**
    44      * Get any renderer parameters.
    44  		* Get any renderer parameters.
    45      *
    45  		*
    46      * @return array  All parameters of this renderer object.
    46  		* @return array  All parameters of this renderer object.
    47      */
    47  		*/
    48     function getParams()
    48 		function getParams()
    49     {
    49 		{
    50         $params = array();
    50 				$params = array();
    51         foreach (get_object_vars($this) as $k => $v) {
    51 				foreach (get_object_vars($this) as $k => $v) {
    52             if ($k[0] == '_') {
    52 						if ($k[0] == '_') {
    53                 $params[substr($k, 1)] = $v;
    53 								$params[substr($k, 1)] = $v;
    54             }
    54 						}
    55         }
    55 				}
    56 
    56 
    57         return $params;
    57 				return $params;
    58     }
    58 		}
    59 
    59 
    60     /**
    60 		/**
    61      * Renders a diff.
    61  		* Renders a diff.
    62      *
    62  		*
    63      * @param Text_Diff $diff  A Text_Diff object.
    63  		* @param Text_Diff $diff  A Text_Diff object.
    64      *
    64  		*
    65      * @return string  The formatted output.
    65  		* @return string  The formatted output.
    66      */
    66  		*/
    67     function render($diff)
    67 		function render($diff)
    68     {
    68 		{
    69         $xi = $yi = 1;
    69 				$xi = $yi = 1;
    70         $block = false;
    70 				$block = false;
    71         $context = array();
    71 				$context = array();
    72 
    72 
    73         $nlead = $this->_leading_context_lines;
    73 				$nlead = $this->_leading_context_lines;
    74         $ntrail = $this->_trailing_context_lines;
    74 				$ntrail = $this->_trailing_context_lines;
    75 
    75 
    76         $output = $this->_startDiff();
    76 				$output = $this->_startDiff();
    77 
    77 
    78         $diffs = $diff->getDiff();
    78 				$diffs = $diff->getDiff();
    79         foreach ($diffs as $i => $edit) {
    79 				foreach ($diffs as $i => $edit) {
    80             if (is_a($edit, 'Text_Diff_Op_copy')) {
    80 						if (is_a($edit, 'Text_Diff_Op_copy')) {
    81                 if (is_array($block)) {
    81 								if (is_array($block)) {
    82                     $keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail;
    82 										$keep = $i == count($diffs) - 1 ? $ntrail : $nlead + $ntrail;
    83                     if (count($edit->orig) <= $keep) {
    83 										if (count($edit->orig) <= $keep) {
    84                         $block[] = $edit;
    84 												$block[] = $edit;
    85                     } else {
    85 										} else {
    86                         if ($ntrail) {
    86 												if ($ntrail) {
    87                             $context = array_slice($edit->orig, 0, $ntrail);
    87 														$context = array_slice($edit->orig, 0, $ntrail);
    88                             $block[] = &new Text_Diff_Op_copy($context);
    88 														$block[] = &new Text_Diff_Op_copy($context);
    89                         }
    89 												}
    90                         $output .= $this->_block($x0, $ntrail + $xi - $x0,
    90 												$output .= $this->_block($x0, $ntrail + $xi - $x0,
    91                                                  $y0, $ntrail + $yi - $y0,
    91  																								$y0, $ntrail + $yi - $y0,
    92                                                  $block);
    92  																								$block);
    93                         $block = false;
    93 												$block = false;
    94                     }
    94 										}
    95                 }
    95 								}
    96                 $context = $edit->orig;
    96 								$context = $edit->orig;
    97             } else {
    97 						} else {
    98                 if (!is_array($block)) {
    98 								if (!is_array($block)) {
    99                     $context = array_slice($context, count($context) - $nlead);
    99 										$context = array_slice($context, count($context) - $nlead);
   100                     $x0 = $xi - count($context);
   100 										$x0 = $xi - count($context);
   101                     $y0 = $yi - count($context);
   101 										$y0 = $yi - count($context);
   102                     $block = array();
   102 										$block = array();
   103                     if ($context) {
   103 										if ($context) {
   104                         $block[] = &new Text_Diff_Op_copy($context);
   104 												$block[] = &new Text_Diff_Op_copy($context);
   105                     }
   105 										}
   106                 }
   106 								}
   107                 $block[] = $edit;
   107 								$block[] = $edit;
   108             }
   108 						}
   109 
   109 
   110             if ($edit->orig) {
   110 						if ($edit->orig) {
   111                 $xi += count($edit->orig);
   111 								$xi += count($edit->orig);
   112             }
   112 						}
   113             if ($edit->final) {
   113 						if ($edit->final) {
   114                 $yi += count($edit->final);
   114 								$yi += count($edit->final);
   115             }
   115 						}
   116         }
   116 				}
   117 
   117 
   118         if (is_array($block)) {
   118 				if (is_array($block)) {
   119             $output .= $this->_block($x0, $xi - $x0,
   119 						$output .= $this->_block($x0, $xi - $x0,
   120                                      $y0, $yi - $y0,
   120  																		$y0, $yi - $y0,
   121                                      $block);
   121  																		$block);
   122         }
   122 				}
   123 
   123 
   124         return $output . $this->_endDiff();
   124 				return $output . $this->_endDiff();
   125     }
   125 		}
   126 
   126 
   127     function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
   127 		function _block($xbeg, $xlen, $ybeg, $ylen, &$edits)
   128     {
   128 		{
   129         $output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen));
   129 				$output = $this->_startBlock($this->_blockHeader($xbeg, $xlen, $ybeg, $ylen));
   130 
   130 
   131         foreach ($edits as $edit) {
   131 				foreach ($edits as $edit) {
   132             switch (strtolower(get_class($edit))) {
   132 						switch (strtolower(get_class($edit))) {
   133             case 'text_diff_op_copy':
   133 						case 'text_diff_op_copy':
   134                 $output .= $this->_context($edit->orig);
   134 								$output .= $this->_context($edit->orig);
   135                 break;
   135 								break;
   136 
   136 
   137             case 'text_diff_op_add':
   137 						case 'text_diff_op_add':
   138                 $output .= $this->_added($edit->final);
   138 								$output .= $this->_added($edit->final);
   139                 break;
   139 								break;
   140 
   140 
   141             case 'text_diff_op_delete':
   141 						case 'text_diff_op_delete':
   142                 $output .= $this->_deleted($edit->orig);
   142 								$output .= $this->_deleted($edit->orig);
   143                 break;
   143 								break;
   144 
   144 
   145             case 'text_diff_op_change':
   145 						case 'text_diff_op_change':
   146                 $output .= $this->_changed($edit->orig, $edit->final);
   146 								$output .= $this->_changed($edit->orig, $edit->final);
   147                 break;
   147 								break;
   148             }
   148 						}
   149         }
   149 				}
   150 
   150 
   151         return $output . $this->_endBlock();
   151 				return $output . $this->_endBlock();
   152     }
   152 		}
   153 
   153 
   154     function _startDiff()
   154 		function _startDiff()
   155     {
   155 		{
   156         return '';
   156 				return '';
   157     }
   157 		}
   158 
   158 
   159     function _endDiff()
   159 		function _endDiff()
   160     {
   160 		{
   161         return '';
   161 				return '';
   162     }
   162 		}
   163 
   163 
   164     function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
   164 		function _blockHeader($xbeg, $xlen, $ybeg, $ylen)
   165     {
   165 		{
   166         if ($xlen > 1) {
   166 				if ($xlen > 1) {
   167             $xbeg .= ',' . ($xbeg + $xlen - 1);
   167 						$xbeg .= ',' . ($xbeg + $xlen - 1);
   168         }
   168 				}
   169         if ($ylen > 1) {
   169 				if ($ylen > 1) {
   170             $ybeg .= ',' . ($ybeg + $ylen - 1);
   170 						$ybeg .= ',' . ($ybeg + $ylen - 1);
   171         }
   171 				}
   172 
   172 
   173         return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
   173 				return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
   174     }
   174 		}
   175 
   175 
   176     function _startBlock($header)
   176 		function _startBlock($header)
   177     {
   177 		{
   178         return $header . "\n";
   178 				return $header . "\n";
   179     }
   179 		}
   180 
   180 
   181     function _endBlock()
   181 		function _endBlock()
   182     {
   182 		{
   183         return '';
   183 				return '';
   184     }
   184 		}
   185 
   185 
   186     function _lines($lines, $prefix = ' ')
   186 		function _lines($lines, $prefix = ' ')
   187     {
   187 		{
   188         return $prefix . implode("\n$prefix", $lines) . "\n";
   188 				return $prefix . implode("\n$prefix", $lines) . "\n";
   189     }
   189 		}
   190 
   190 
   191     function _context($lines)
   191 		function _context($lines)
   192     {
   192 		{
   193         return $this->_lines($lines);
   193 				return $this->_lines($lines);
   194     }
   194 		}
   195 
   195 
   196     function _added($lines)
   196 		function _added($lines)
   197     {
   197 		{
   198         return $this->_lines($lines, '>');
   198 				return $this->_lines($lines, '>');
   199     }
   199 		}
   200 
   200 
   201     function _deleted($lines)
   201 		function _deleted($lines)
   202     {
   202 		{
   203         return $this->_lines($lines, '<');
   203 				return $this->_lines($lines, '<');
   204     }
   204 		}
   205 
   205 
   206     function _changed($orig, $final)
   206 		function _changed($orig, $final)
   207     {
   207 		{
   208         return $this->_deleted($orig) . "---\n" . $this->_added($final);
   208 				return $this->_deleted($orig) . "---\n" . $this->_added($final);
   209     }
   209 		}
   210 
   210 
   211 }
   211 }