MediaWiki  REL1_24
DiffFormatter.php
Go to the documentation of this file.
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 }