MediaWiki
REL1_24
|
00001 <?php 00036 abstract class DiffFormatter { 00037 00043 protected $leadingContextLines = 0; 00044 00050 protected $trailingContextLines = 0; 00051 00059 public function format( $diff ) { 00060 wfProfileIn( __METHOD__ ); 00061 00062 $xi = $yi = 1; 00063 $block = false; 00064 $context = array(); 00065 00066 $nlead = $this->leadingContextLines; 00067 $ntrail = $this->trailingContextLines; 00068 00069 $this->startDiff(); 00070 00071 // Initialize $x0 and $y0 to prevent IDEs from getting confused. 00072 $x0 = $y0 = 0; 00073 foreach ( $diff->edits as $edit ) { 00074 if ( $edit->type == 'copy' ) { 00075 if ( is_array( $block ) ) { 00076 if ( count( $edit->orig ) <= $nlead + $ntrail ) { 00077 $block[] = $edit; 00078 } else { 00079 if ( $ntrail ) { 00080 $context = array_slice( $edit->orig, 0, $ntrail ); 00081 $block[] = new DiffOpCopy( $context ); 00082 } 00083 $this->block( $x0, $ntrail + $xi - $x0, 00084 $y0, $ntrail + $yi - $y0, 00085 $block ); 00086 $block = false; 00087 } 00088 } 00089 $context = $edit->orig; 00090 } else { 00091 if ( !is_array( $block ) ) { 00092 $context = array_slice( $context, count( $context ) - $nlead ); 00093 $x0 = $xi - count( $context ); 00094 $y0 = $yi - count( $context ); 00095 $block = array(); 00096 if ( $context ) { 00097 $block[] = new DiffOpCopy( $context ); 00098 } 00099 } 00100 $block[] = $edit; 00101 } 00102 00103 if ( $edit->orig ) { 00104 $xi += count( $edit->orig ); 00105 } 00106 if ( $edit->closing ) { 00107 $yi += count( $edit->closing ); 00108 } 00109 } 00110 00111 if ( is_array( $block ) ) { 00112 $this->block( $x0, $xi - $x0, 00113 $y0, $yi - $y0, 00114 $block ); 00115 } 00116 00117 $end = $this->endDiff(); 00118 wfProfileOut( __METHOD__ ); 00119 00120 return $end; 00121 } 00122 00132 protected function block( $xbeg, $xlen, $ybeg, $ylen, &$edits ) { 00133 wfProfileIn( __METHOD__ ); 00134 $this->startBlock( $this->blockHeader( $xbeg, $xlen, $ybeg, $ylen ) ); 00135 foreach ( $edits as $edit ) { 00136 if ( $edit->type == 'copy' ) { 00137 $this->context( $edit->orig ); 00138 } elseif ( $edit->type == 'add' ) { 00139 $this->added( $edit->closing ); 00140 } elseif ( $edit->type == 'delete' ) { 00141 $this->deleted( $edit->orig ); 00142 } elseif ( $edit->type == 'change' ) { 00143 $this->changed( $edit->orig, $edit->closing ); 00144 } else { 00145 throw new MWException( "Unknown edit type: {$edit->type}" ); 00146 } 00147 } 00148 $this->endBlock(); 00149 wfProfileOut( __METHOD__ ); 00150 } 00151 00152 protected function startDiff() { 00153 ob_start(); 00154 } 00155 00159 protected function endDiff() { 00160 $val = ob_get_contents(); 00161 ob_end_clean(); 00162 00163 return $val; 00164 } 00165 00174 protected function blockHeader( $xbeg, $xlen, $ybeg, $ylen ) { 00175 if ( $xlen > 1 ) { 00176 $xbeg .= ',' . ( $xbeg + $xlen - 1 ); 00177 } 00178 if ( $ylen > 1 ) { 00179 $ybeg .= ',' . ( $ybeg + $ylen - 1 ); 00180 } 00181 00182 return $xbeg . ( $xlen ? ( $ylen ? 'c' : 'd' ) : 'a' ) . $ybeg; 00183 } 00184 00191 protected function startBlock( $header ) { 00192 echo $header . "\n"; 00193 } 00194 00199 protected function endBlock() { 00200 } 00201 00208 protected function lines( $lines, $prefix = ' ' ) { 00209 foreach ( $lines as $line ) { 00210 echo "$prefix $line\n"; 00211 } 00212 } 00213 00217 protected function context( $lines ) { 00218 $this->lines( $lines ); 00219 } 00220 00224 protected function added( $lines ) { 00225 $this->lines( $lines, '>' ); 00226 } 00227 00231 protected function deleted( $lines ) { 00232 $this->lines( $lines, '<' ); 00233 } 00234 00241 protected function changed( $orig, $closing ) { 00242 $this->deleted( $orig ); 00243 echo "---\n"; 00244 $this->added( $closing ); 00245 } 00246 00247 }