summaryrefslogtreecommitdiff
path: root/includes/diff
diff options
context:
space:
mode:
authorPierre Schmitz <pierre@archlinux.de>2011-12-03 13:29:22 +0100
committerPierre Schmitz <pierre@archlinux.de>2011-12-03 13:29:22 +0100
commitca32f08966f1b51fcb19460f0996bb0c4048e6fe (patch)
treeec04cc15b867bc21eedca904cea9af0254531a11 /includes/diff
parenta22fbfc60f36f5f7ee10d5ae6fe347340c2ee67c (diff)
Update to MediaWiki 1.18.0
* also update ArchLinux skin to chagnes in MonoBook * Use only css to hide our menu bar when printing
Diffstat (limited to 'includes/diff')
-rw-r--r--includes/diff/DairikiDiff.php (renamed from includes/diff/WikiDiff.php)450
-rw-r--r--includes/diff/DifferenceEngine.php259
-rw-r--r--includes/diff/WikiDiff3.php14
3 files changed, 429 insertions, 294 deletions
diff --git a/includes/diff/WikiDiff.php b/includes/diff/DairikiDiff.php
index 2d904c96..8f19712b 100644
--- a/includes/diff/WikiDiff.php
+++ b/includes/diff/DairikiDiff.php
@@ -41,9 +41,10 @@ class _DiffOp {
class _DiffOp_Copy extends _DiffOp {
var $type = 'copy';
- function __construct ( $orig, $closing = false ) {
- if ( !is_array( $closing ) )
- $closing = $orig;
+ function __construct( $orig, $closing = false ) {
+ if ( !is_array( $closing ) ) {
+ $closing = $orig;
+ }
$this->orig = $orig;
$this->closing = $closing;
}
@@ -61,7 +62,7 @@ class _DiffOp_Copy extends _DiffOp {
class _DiffOp_Delete extends _DiffOp {
var $type = 'delete';
- function __construct ( $lines ) {
+ function __construct( $lines ) {
$this->orig = $lines;
$this->closing = false;
}
@@ -79,7 +80,7 @@ class _DiffOp_Delete extends _DiffOp {
class _DiffOp_Add extends _DiffOp {
var $type = 'add';
- function __construct ( $lines ) {
+ function __construct( $lines ) {
$this->closing = $lines;
$this->orig = false;
}
@@ -97,7 +98,7 @@ class _DiffOp_Add extends _DiffOp {
class _DiffOp_Change extends _DiffOp {
var $type = 'change';
- function __construct ( $orig, $closing ) {
+ function __construct( $orig, $closing ) {
$this->orig = $orig;
$this->closing = $closing;
}
@@ -135,6 +136,15 @@ class _DiffEngine {
const MAX_XREF_LENGTH = 10000;
+ protected $xchanged, $ychanged;
+
+ protected $xv = array(), $yv = array();
+ protected $xind = array(), $yind = array();
+
+ protected $seq = array(), $in_seq = array();
+
+ protected $lcs = 0;
+
function diff ( $from_lines, $to_lines ) {
wfProfileIn( __METHOD__ );
@@ -162,24 +172,28 @@ class _DiffEngine {
$copy[] = $from_lines[$xi++];
++$yi;
}
- if ( $copy )
- $edits[] = new _DiffOp_Copy( $copy );
+ if ( $copy ) {
+ $edits[] = new _DiffOp_Copy( $copy );
+ }
// Find deletes & adds.
$delete = array();
- while ( $xi < $n_from && $this->xchanged[$xi] )
- $delete[] = $from_lines[$xi++];
+ while ( $xi < $n_from && $this->xchanged[$xi] ) {
+ $delete[] = $from_lines[$xi++];
+ }
$add = array();
- while ( $yi < $n_to && $this->ychanged[$yi] )
- $add[] = $to_lines[$yi++];
-
- if ( $delete && $add )
- $edits[] = new _DiffOp_Change( $delete, $add );
- elseif ( $delete )
- $edits[] = new _DiffOp_Delete( $delete );
- elseif ( $add )
- $edits[] = new _DiffOp_Add( $add );
+ while ( $yi < $n_to && $this->ychanged[$yi] ) {
+ $add[] = $to_lines[$yi++];
+ }
+
+ if ( $delete && $add ) {
+ $edits[] = new _DiffOp_Change( $delete, $add );
+ } elseif ( $delete ) {
+ $edits[] = new _DiffOp_Delete( $delete );
+ } elseif ( $add ) {
+ $edits[] = new _DiffOp_Add( $add );
+ }
}
wfProfileOut( __METHOD__ );
return $edits;
@@ -209,15 +223,17 @@ class _DiffEngine {
// Skip leading common lines.
for ( $skip = 0; $skip < $n_from && $skip < $n_to; $skip++ ) {
- if ( $from_lines[$skip] !== $to_lines[$skip] )
- break;
+ if ( $from_lines[$skip] !== $to_lines[$skip] ) {
+ break;
+ }
$this->xchanged[$skip] = $this->ychanged[$skip] = false;
}
// Skip trailing common lines.
$xi = $n_from; $yi = $n_to;
for ( $endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++ ) {
- if ( $from_lines[$xi] !== $to_lines[$yi] )
- break;
+ if ( $from_lines[$xi] !== $to_lines[$yi] ) {
+ break;
+ }
$this->xchanged[$xi] = $this->ychanged[$yi] = false;
}
@@ -228,16 +244,18 @@ class _DiffEngine {
for ( $yi = $skip; $yi < $n_to - $endskip; $yi++ ) {
$line = $to_lines[$yi];
- if ( ( $this->ychanged[$yi] = empty( $xhash[$this->_line_hash( $line )] ) ) )
- continue;
+ if ( ( $this->ychanged[$yi] = empty( $xhash[$this->_line_hash( $line )] ) ) ) {
+ continue;
+ }
$yhash[$this->_line_hash( $line )] = 1;
$this->yv[] = $line;
$this->yind[] = $yi;
}
for ( $xi = $skip; $xi < $n_from - $endskip; $xi++ ) {
$line = $from_lines[$xi];
- if ( ( $this->xchanged[$xi] = empty( $yhash[$this->_line_hash( $line )] ) ) )
- continue;
+ if ( ( $this->xchanged[$xi] = empty( $yhash[$this->_line_hash( $line )] ) ) ) {
+ continue;
+ }
$this->xv[] = $line;
$this->xind[] = $xi;
}
@@ -259,7 +277,8 @@ class _DiffEngine {
}
}
- /* Divide the Largest Common Subsequence (LCS) of the sequences
+ /**
+ * Divide the Largest Common Subsequence (LCS) of the sequences
* [XOFF, XLIM) and [YOFF, YLIM) into NCHUNKS approximately equally
* sized segments.
*
@@ -275,23 +294,25 @@ class _DiffEngine {
* match. The caller must trim matching lines from the beginning and end
* of the portions it is going to specify.
*/
- function _diag ( $xoff, $xlim, $yoff, $ylim, $nchunks ) {
+ function _diag( $xoff, $xlim, $yoff, $ylim, $nchunks ) {
$flip = false;
if ( $xlim - $xoff > $ylim - $yoff ) {
// Things seems faster (I'm not sure I understand why)
// when the shortest sequence in X.
$flip = true;
- list ( $xoff, $xlim, $yoff, $ylim )
- = array( $yoff, $ylim, $xoff, $xlim );
+ list( $xoff, $xlim, $yoff, $ylim ) = array( $yoff, $ylim, $xoff, $xlim );
}
- if ( $flip )
- for ( $i = $ylim - 1; $i >= $yoff; $i-- )
- $ymatches[$this->xv[$i]][] = $i;
- else
- for ( $i = $ylim - 1; $i >= $yoff; $i-- )
- $ymatches[$this->yv[$i]][] = $i;
+ if ( $flip ) {
+ for ( $i = $ylim - 1; $i >= $yoff; $i-- ) {
+ $ymatches[$this->xv[$i]][] = $i;
+ }
+ } else {
+ for ( $i = $ylim - 1; $i >= $yoff; $i-- ) {
+ $ymatches[$this->yv[$i]][] = $i;
+ }
+ }
$this->lcs = 0;
$this->seq[0] = $yoff - 1;
@@ -301,9 +322,11 @@ class _DiffEngine {
$numer = $xlim - $xoff + $nchunks - 1;
$x = $xoff;
for ( $chunk = 0; $chunk < $nchunks; $chunk++ ) {
- if ( $chunk > 0 )
- for ( $i = 0; $i <= $this->lcs; $i++ )
- $ymids[$i][$chunk -1] = $this->seq[$i];
+ if ( $chunk > 0 ) {
+ for ( $i = 0; $i <= $this->lcs; $i++ ) {
+ $ymids[$i][$chunk -1] = $this->seq[$i];
+ }
+ }
$x1 = $xoff + (int)( ( $numer + ( $xlim -$xoff ) * $chunk ) / $nchunks );
for ( ; $x < $x1; $x++ ) {
@@ -329,7 +352,7 @@ class _DiffEngine {
$this->in_seq[$this->seq[$k]] = false;
$this->seq[$k] = $y;
$this->in_seq[$y] = 1;
- } else if ( empty( $this->in_seq[$y] ) ) {
+ } elseif ( empty( $this->in_seq[$y] ) ) {
$k = $this->_lcs_pos( $y );
assert( $k > 0 );
$ymids[$k] = $ymids[$k -1];
@@ -350,7 +373,7 @@ class _DiffEngine {
return array( $this->lcs, $seps );
}
- function _lcs_pos ( $ypos ) {
+ function _lcs_pos( $ypos ) {
$end = $this->lcs;
if ( $end == 0 || $ypos > $this->seq[$end] ) {
$this->seq[++$this->lcs] = $ypos;
@@ -361,10 +384,11 @@ class _DiffEngine {
$beg = 1;
while ( $beg < $end ) {
$mid = (int)( ( $beg + $end ) / 2 );
- if ( $ypos > $this->seq[$mid] )
- $beg = $mid + 1;
- else
- $end = $mid;
+ if ( $ypos > $this->seq[$mid] ) {
+ $beg = $mid + 1;
+ } else {
+ $end = $mid;
+ }
}
assert( $ypos != $this->seq[$end] );
@@ -375,7 +399,8 @@ class _DiffEngine {
return $end;
}
- /* Find LCS of two sequences.
+ /**
+ * Find LCS of two sequences.
*
* The results are recorded in the vectors $this->{x,y}changed[], by
* storing a 1 in the element for each line that is an insertion
@@ -401,9 +426,9 @@ class _DiffEngine {
--$ylim;
}
- if ( $xoff == $xlim || $yoff == $ylim )
- $lcs = 0;
- else {
+ if ( $xoff == $xlim || $yoff == $ylim ) {
+ $lcs = 0;
+ } else {
// This is ad hoc but seems to work well.
// $nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5);
// $nchunks = max(2,min(8,(int)$nchunks));
@@ -415,10 +440,12 @@ class _DiffEngine {
if ( $lcs == 0 ) {
// X and Y sequences have no common subsequence:
// mark all changed.
- while ( $yoff < $ylim )
- $this->ychanged[$this->yind[$yoff++]] = 1;
- while ( $xoff < $xlim )
- $this->xchanged[$this->xind[$xoff++]] = 1;
+ while ( $yoff < $ylim ) {
+ $this->ychanged[$this->yind[$yoff++]] = 1;
+ }
+ while ( $xoff < $xlim ) {
+ $this->xchanged[$this->xind[$xoff++]] = 1;
+ }
} else {
// Use the partitions to split this problem into subproblems.
reset( $seps );
@@ -430,7 +457,8 @@ class _DiffEngine {
}
}
- /* Adjust inserts/deletes of identical lines to join changes
+ /**
+ * Adjust inserts/deletes of identical lines to join changes
* as much as possible.
*
* We do something when a run of changed lines include a
@@ -442,7 +470,7 @@ class _DiffEngine {
*
* This is extracted verbatim from analyze.c (GNU diffutils-2.7).
*/
- function _shift_boundaries ( $lines, &$changed, $other_changed ) {
+ function _shift_boundaries( $lines, &$changed, $other_changed ) {
wfProfileIn( __METHOD__ );
$i = 0;
$j = 0;
@@ -463,8 +491,9 @@ class _DiffEngine {
* Furthermore, $j is always kept so that $j == $other_len or
* $other_changed[$j] == false.
*/
- while ( $j < $other_len && $other_changed[$j] )
- $j++;
+ while ( $j < $other_len && $other_changed[$j] ) {
+ $j++;
+ }
while ( $i < $len && ! $changed[$i] ) {
assert( '$j < $other_len && ! $other_changed[$j]' );
@@ -473,14 +502,16 @@ class _DiffEngine {
$j++;
}
- if ( $i == $len )
- break;
+ if ( $i == $len ) {
+ break;
+ }
$start = $i;
// Find the end of this run of changes.
- while ( ++$i < $len && $changed[$i] )
- continue;
+ while ( ++$i < $len && $changed[$i] ) {
+ continue;
+ }
do {
/*
@@ -497,11 +528,13 @@ class _DiffEngine {
while ( $start > 0 && $lines[$start - 1] == $lines[$i - 1] ) {
$changed[--$start] = 1;
$changed[--$i] = false;
- while ( $start > 0 && $changed[$start - 1] )
- $start--;
+ while ( $start > 0 && $changed[$start - 1] ) {
+ $start--;
+ }
assert( '$j > 0' );
- while ( $other_changed[--$j] )
- continue;
+ while ( $other_changed[--$j] ) {
+ continue;
+ }
assert( '$j >= 0 && !$other_changed[$j]' );
}
@@ -522,15 +555,17 @@ class _DiffEngine {
while ( $i < $len && $lines[$start] == $lines[$i] ) {
$changed[$start++] = false;
$changed[$i++] = 1;
- while ( $i < $len && $changed[$i] )
- $i++;
+ while ( $i < $len && $changed[$i] ) {
+ $i++;
+ }
assert( '$j < $other_len && ! $other_changed[$j]' );
$j++;
if ( $j < $other_len && $other_changed[$j] ) {
$corresponding = $i;
- while ( $j < $other_len && $other_changed[$j] )
- $j++;
+ while ( $j < $other_len && $other_changed[$j] ) {
+ $j++;
+ }
}
}
} while ( $runlength != $i - $start );
@@ -543,8 +578,9 @@ class _DiffEngine {
$changed[--$start] = 1;
$changed[--$i] = 0;
assert( '$j > 0' );
- while ( $other_changed[--$j] )
- continue;
+ while ( $other_changed[--$j] ) {
+ continue;
+ }
assert( '$j >= 0 && !$other_changed[$j]' );
}
}
@@ -558,8 +594,7 @@ class _DiffEngine {
* @private
* @ingroup DifferenceEngine
*/
-class Diff
-{
+class Diff {
var $edits;
/**
@@ -586,7 +621,7 @@ class Diff
* @return object A Diff object representing the inverse of the
* original diff.
*/
- function reverse () {
+ function reverse() {
$rev = $this;
$rev->edits = array();
foreach ( $this->edits as $edit ) {
@@ -600,10 +635,11 @@ class Diff
*
* @return bool True iff two sequences were identical.
*/
- function isEmpty () {
+ function isEmpty() {
foreach ( $this->edits as $edit ) {
- if ( $edit->type != 'copy' )
- return false;
+ if ( $edit->type != 'copy' ) {
+ return false;
+ }
}
return true;
}
@@ -615,11 +651,12 @@ class Diff
*
* @return int The length of the LCS.
*/
- function lcs () {
+ function lcs() {
$lcs = 0;
foreach ( $this->edits as $edit ) {
- if ( $edit->type == 'copy' )
- $lcs += sizeof( $edit->orig );
+ if ( $edit->type == 'copy' ) {
+ $lcs += sizeof( $edit->orig );
+ }
}
return $lcs;
}
@@ -636,8 +673,9 @@ class Diff
$lines = array();
foreach ( $this->edits as $edit ) {
- if ( $edit->orig )
- array_splice( $lines, sizeof( $lines ), 0, $edit->orig );
+ if ( $edit->orig ) {
+ array_splice( $lines, sizeof( $lines ), 0, $edit->orig );
+ }
}
return $lines;
}
@@ -654,8 +692,9 @@ class Diff
$lines = array();
foreach ( $this->edits as $edit ) {
- if ( $edit->closing )
- array_splice( $lines, sizeof( $lines ), 0, $edit->closing );
+ if ( $edit->closing ) {
+ array_splice( $lines, sizeof( $lines ), 0, $edit->closing );
+ }
}
return $lines;
}
@@ -665,24 +704,29 @@ class Diff
*
* This is here only for debugging purposes.
*/
- function _check ( $from_lines, $to_lines ) {
+ function _check( $from_lines, $to_lines ) {
wfProfileIn( __METHOD__ );
- if ( serialize( $from_lines ) != serialize( $this->orig() ) )
- trigger_error( "Reconstructed original doesn't match", E_USER_ERROR );
- if ( serialize( $to_lines ) != serialize( $this->closing() ) )
- trigger_error( "Reconstructed closing doesn't match", E_USER_ERROR );
+ if ( serialize( $from_lines ) != serialize( $this->orig() ) ) {
+ trigger_error( "Reconstructed original doesn't match", E_USER_ERROR );
+ }
+ if ( serialize( $to_lines ) != serialize( $this->closing() ) ) {
+ trigger_error( "Reconstructed closing doesn't match", E_USER_ERROR );
+ }
$rev = $this->reverse();
- if ( serialize( $to_lines ) != serialize( $rev->orig() ) )
- trigger_error( "Reversed original doesn't match", E_USER_ERROR );
- if ( serialize( $from_lines ) != serialize( $rev->closing() ) )
- trigger_error( "Reversed closing doesn't match", E_USER_ERROR );
+ if ( serialize( $to_lines ) != serialize( $rev->orig() ) ) {
+ trigger_error( "Reversed original doesn't match", E_USER_ERROR );
+ }
+ if ( serialize( $from_lines ) != serialize( $rev->closing() ) ) {
+ trigger_error( "Reversed closing doesn't match", E_USER_ERROR );
+ }
$prevtype = 'none';
foreach ( $this->edits as $edit ) {
- if ( $prevtype == $edit->type )
- trigger_error( "Edit sequence is non-optimal", E_USER_ERROR );
+ if ( $prevtype == $edit->type ) {
+ trigger_error( 'Edit sequence is non-optimal', E_USER_ERROR );
+ }
$prevtype = $edit->type;
}
@@ -697,8 +741,7 @@ class Diff
* @private
* @ingroup DifferenceEngine
*/
-class MappedDiff extends Diff
-{
+class MappedDiff extends Diff {
/**
* Constructor.
*
@@ -723,7 +766,7 @@ class MappedDiff extends Diff
* have the same number of elements as $to_lines.
*/
function __construct( $from_lines, $to_lines,
- $mapped_from_lines, $mapped_to_lines ) {
+ $mapped_from_lines, $mapped_to_lines ) {
wfProfileIn( __METHOD__ );
assert( sizeof( $from_lines ) == sizeof( $mapped_from_lines ) );
@@ -779,7 +822,7 @@ class DiffFormatter {
/**
* Format a diff.
*
- * @param $diff object A Diff object.
+ * @param $diff Diff A Diff object.
* @return string The formatted output.
*/
function format( $diff ) {
@@ -799,42 +842,44 @@ class DiffFormatter {
if ( is_array( $block ) ) {
if ( sizeof( $edit->orig ) <= $nlead + $ntrail ) {
$block[] = $edit;
- }
- else {
+ } else {
if ( $ntrail ) {
$context = array_slice( $edit->orig, 0, $ntrail );
$block[] = new _DiffOp_Copy( $context );
}
$this->_block( $x0, $ntrail + $xi - $x0,
- $y0, $ntrail + $yi - $y0,
- $block );
+ $y0, $ntrail + $yi - $y0,
+ $block );
$block = false;
}
}
$context = $edit->orig;
- }
- else {
- if ( ! is_array( $block ) ) {
+ } else {
+ if ( !is_array( $block ) ) {
$context = array_slice( $context, sizeof( $context ) - $nlead );
$x0 = $xi - sizeof( $context );
$y0 = $yi - sizeof( $context );
$block = array();
- if ( $context )
- $block[] = new _DiffOp_Copy( $context );
+ if ( $context ) {
+ $block[] = new _DiffOp_Copy( $context );
+ }
}
$block[] = $edit;
}
- if ( $edit->orig )
- $xi += sizeof( $edit->orig );
- if ( $edit->closing )
- $yi += sizeof( $edit->closing );
+ if ( $edit->orig ) {
+ $xi += sizeof( $edit->orig );
+ }
+ if ( $edit->closing ) {
+ $yi += sizeof( $edit->closing );
+ }
}
- if ( is_array( $block ) )
- $this->_block( $x0, $xi - $x0,
- $y0, $yi - $y0,
- $block );
+ if ( is_array( $block ) ) {
+ $this->_block( $x0, $xi - $x0,
+ $y0, $yi - $y0,
+ $block );
+ }
$end = $this->_end_diff();
wfProfileOut( __METHOD__ );
@@ -845,16 +890,17 @@ class DiffFormatter {
wfProfileIn( __METHOD__ );
$this->_start_block( $this->_block_header( $xbeg, $xlen, $ybeg, $ylen ) );
foreach ( $edits as $edit ) {
- if ( $edit->type == 'copy' )
- $this->_context( $edit->orig );
- elseif ( $edit->type == 'add' )
- $this->_added( $edit->closing );
- elseif ( $edit->type == 'delete' )
- $this->_deleted( $edit->orig );
- elseif ( $edit->type == 'change' )
- $this->_changed( $edit->orig, $edit->closing );
- else
- trigger_error( 'Unknown edit type', E_USER_ERROR );
+ if ( $edit->type == 'copy' ) {
+ $this->_context( $edit->orig );
+ } elseif ( $edit->type == 'add' ) {
+ $this->_added( $edit->closing );
+ } elseif ( $edit->type == 'delete' ) {
+ $this->_deleted( $edit->orig );
+ } elseif ( $edit->type == 'change' ) {
+ $this->_changed( $edit->orig, $edit->closing );
+ } else {
+ trigger_error( 'Unknown edit type', E_USER_ERROR );
+ }
}
$this->_end_block();
wfProfileOut( __METHOD__ );
@@ -871,10 +917,12 @@ class DiffFormatter {
}
function _block_header( $xbeg, $xlen, $ybeg, $ylen ) {
- if ( $xlen > 1 )
- $xbeg .= "," . ( $xbeg + $xlen - 1 );
- if ( $ylen > 1 )
- $ybeg .= "," . ( $ybeg + $ylen - 1 );
+ if ( $xlen > 1 ) {
+ $xbeg .= ',' . ( $xbeg + $xlen - 1 );
+ }
+ if ( $ylen > 1 ) {
+ $ybeg .= ',' . ( $ybeg + $ylen - 1 );
+ }
return $xbeg . ( $xlen ? ( $ylen ? 'c' : 'd' ) : 'a' ) . $ybeg;
}
@@ -887,8 +935,9 @@ class DiffFormatter {
}
function _lines( $lines, $prefix = ' ' ) {
- foreach ( $lines as $line )
- echo "$prefix $line\n";
+ foreach ( $lines as $line ) {
+ echo "$prefix $line\n";
+ }
}
function _context( $lines ) {
@@ -913,7 +962,6 @@ class DiffFormatter {
* A formatter that outputs unified diffs
* @ingroup DifferenceEngine
*/
-
class UnifiedDiffFormatter extends DiffFormatter {
var $leading_context_lines = 2;
var $trailing_context_lines = 2;
@@ -942,48 +990,48 @@ class ArrayDiffFormatter extends DiffFormatter {
$oldline = 1;
$newline = 1;
$retval = array();
- foreach ( $diff->edits as $edit )
- switch( $edit->type ) {
- case 'add':
- foreach ( $edit->closing as $l ) {
- $retval[] = array(
+ foreach ( $diff->edits as $edit ) {
+ switch( $edit->type ) {
+ case 'add':
+ foreach ( $edit->closing as $l ) {
+ $retval[] = array(
'action' => 'add',
'new' => $l,
'newline' => $newline++
- );
- }
- break;
- case 'delete':
- foreach ( $edit->orig as $l ) {
- $retval[] = array(
+ );
+ }
+ break;
+ case 'delete':
+ foreach ( $edit->orig as $l ) {
+ $retval[] = array(
'action' => 'delete',
'old' => $l,
'oldline' => $oldline++,
- );
- }
- break;
- case 'change':
- foreach ( $edit->orig as $i => $l ) {
- $retval[] = array(
+ );
+ }
+ break;
+ case 'change':
+ foreach ( $edit->orig as $i => $l ) {
+ $retval[] = array(
'action' => 'change',
'old' => $l,
- 'new' => @$edit->closing[$i],
+ 'new' => isset( $edit->closing[$i] ) ? $edit->closing[$i] : null,
'oldline' => $oldline++,
'newline' => $newline++,
- );
- }
- break;
- case 'copy':
- $oldline += count( $edit->orig );
- $newline += count( $edit->orig );
+ );
+ }
+ break;
+ case 'copy':
+ $oldline += count( $edit->orig );
+ $newline += count( $edit->orig );
+ }
}
return $retval;
}
}
/**
- * Additions by Axel Boldt follow, partly taken from diff.php, phpwiki-1.3.3
- *
+ * Additions by Axel Boldt follow, partly taken from diff.php, phpwiki-1.3.3
*/
define( 'NBSP', '&#160;' ); // iso-8859-x non-breaking space.
@@ -994,46 +1042,50 @@ define( 'NBSP', '&#160;' ); // iso-8859-x non-breaking space.
* @ingroup DifferenceEngine
*/
class _HWLDF_WordAccumulator {
- function __construct () {
+ function __construct() {
$this->_lines = array();
$this->_line = '';
$this->_group = '';
$this->_tag = '';
}
- function _flushGroup ( $new_tag ) {
+ function _flushGroup( $new_tag ) {
if ( $this->_group !== '' ) {
- if ( $this->_tag == 'ins' )
- $this->_line .= '<ins class="diffchange diffchange-inline">' .
- htmlspecialchars ( $this->_group ) . '</ins>';
- elseif ( $this->_tag == 'del' )
- $this->_line .= '<del class="diffchange diffchange-inline">' .
- htmlspecialchars ( $this->_group ) . '</del>';
- else
- $this->_line .= htmlspecialchars ( $this->_group );
+ if ( $this->_tag == 'ins' ) {
+ $this->_line .= '<ins class="diffchange diffchange-inline">' .
+ htmlspecialchars( $this->_group ) . '</ins>';
+ } elseif ( $this->_tag == 'del' ) {
+ $this->_line .= '<del class="diffchange diffchange-inline">' .
+ htmlspecialchars( $this->_group ) . '</del>';
+ } else {
+ $this->_line .= htmlspecialchars( $this->_group );
+ }
}
$this->_group = '';
$this->_tag = $new_tag;
}
- function _flushLine ( $new_tag ) {
+ function _flushLine( $new_tag ) {
$this->_flushGroup( $new_tag );
- if ( $this->_line != '' )
- array_push ( $this->_lines, $this->_line );
- else
- # make empty lines visible by inserting an NBSP
- array_push ( $this->_lines, NBSP );
+ if ( $this->_line != '' ) {
+ array_push( $this->_lines, $this->_line );
+ } else {
+ # make empty lines visible by inserting an NBSP
+ array_push( $this->_lines, NBSP );
+ }
$this->_line = '';
}
function addWords ( $words, $tag = '' ) {
- if ( $tag != $this->_tag )
- $this->_flushGroup( $tag );
+ if ( $tag != $this->_tag ) {
+ $this->_flushGroup( $tag );
+ }
foreach ( $words as $word ) {
// new-line should only come as first char of word.
- if ( $word == '' )
- continue;
+ if ( $word == '' ) {
+ continue;
+ }
if ( $word[0] == "\n" ) {
$this->_flushLine( $tag );
$word = substr( $word, 1 );
@@ -1060,8 +1112,8 @@ class WordLevelDiff extends MappedDiff {
function __construct ( $orig_lines, $closing_lines ) {
wfProfileIn( __METHOD__ );
- list ( $orig_words, $orig_stripped ) = $this->_split( $orig_lines );
- list ( $closing_words, $closing_stripped ) = $this->_split( $closing_lines );
+ list( $orig_words, $orig_stripped ) = $this->_split( $orig_lines );
+ list( $closing_words, $closing_stripped ) = $this->_split( $closing_lines );
parent::__construct( $orig_words, $closing_words,
$orig_stripped, $closing_stripped );
@@ -1089,7 +1141,7 @@ class WordLevelDiff extends MappedDiff {
} else {
$m = array();
if ( preg_match_all( '/ ( [^\S\n]+ | [0-9_A-Za-z\x80-\xff]+ | . ) (?: (?!< \n) [^\S\n])? /xs',
- $line, $m ) )
+ $line, $m ) )
{
$words = array_merge( $words, $m[0] );
$stripped = array_merge( $stripped, $m[1] );
@@ -1100,30 +1152,32 @@ class WordLevelDiff extends MappedDiff {
return array( $words, $stripped );
}
- function orig () {
+ function orig() {
wfProfileIn( __METHOD__ );
$orig = new _HWLDF_WordAccumulator;
foreach ( $this->edits as $edit ) {
- if ( $edit->type == 'copy' )
- $orig->addWords( $edit->orig );
- elseif ( $edit->orig )
- $orig->addWords( $edit->orig, 'del' );
+ if ( $edit->type == 'copy' ) {
+ $orig->addWords( $edit->orig );
+ } elseif ( $edit->orig ) {
+ $orig->addWords( $edit->orig, 'del' );
+ }
}
$lines = $orig->getLines();
wfProfileOut( __METHOD__ );
return $lines;
}
- function closing () {
+ function closing() {
wfProfileIn( __METHOD__ );
$closing = new _HWLDF_WordAccumulator;
foreach ( $this->edits as $edit ) {
- if ( $edit->type == 'copy' )
- $closing->addWords( $edit->closing );
- elseif ( $edit->closing )
- $closing->addWords( $edit->closing, 'ins' );
+ if ( $edit->type == 'copy' ) {
+ $closing->addWords( $edit->closing );
+ } elseif ( $edit->closing ) {
+ $closing->addWords( $edit->closing, 'ins' );
+ }
}
$lines = $closing->getLines();
wfProfileOut( __METHOD__ );
@@ -1173,7 +1227,7 @@ class TableDiffFormatter extends DiffFormatter {
# HTML-escape parameter before calling this
function deletedLine( $line ) {
- return $this->wrapLine( '&minus;', 'diff-deletedline', $line );
+ return $this->wrapLine( '−', 'diff-deletedline', $line );
}
# HTML-escape parameter before calling this
@@ -1197,14 +1251,14 @@ class TableDiffFormatter extends DiffFormatter {
foreach ( $lines as $line ) {
echo '<tr>' . $this->emptyLine() .
$this->addedLine( '<ins class="diffchange">' .
- htmlspecialchars ( $line ) . '</ins>' ) . "</tr>\n";
+ htmlspecialchars( $line ) . '</ins>' ) . "</tr>\n";
}
}
function _deleted( $lines ) {
foreach ( $lines as $line ) {
echo '<tr>' . $this->deletedLine( '<del class="diffchange">' .
- htmlspecialchars ( $line ) . '</del>' ) .
+ htmlspecialchars( $line ) . '</del>' ) .
$this->emptyLine() . "</tr>\n";
}
}
@@ -1212,8 +1266,8 @@ class TableDiffFormatter extends DiffFormatter {
function _context( $lines ) {
foreach ( $lines as $line ) {
echo '<tr>' .
- $this->contextLine( htmlspecialchars ( $line ) ) .
- $this->contextLine( htmlspecialchars ( $line ) ) . "</tr>\n";
+ $this->contextLine( htmlspecialchars( $line ) ) .
+ $this->contextLine( htmlspecialchars( $line ) ) . "</tr>\n";
}
}
diff --git a/includes/diff/DifferenceEngine.php b/includes/diff/DifferenceEngine.php
index edf35a92..5902461b 100644
--- a/includes/diff/DifferenceEngine.php
+++ b/includes/diff/DifferenceEngine.php
@@ -22,11 +22,19 @@ class DifferenceEngine {
/**#@+
* @private
*/
- var $mOldid, $mNewid, $mTitle;
+ var $mOldid, $mNewid;
var $mOldtitle, $mNewtitle, $mPagetitle;
var $mOldtext, $mNewtext;
- var $mOldPage, $mNewPage;
+
+ /**
+ * @var Title
+ */
+ var $mOldPage, $mNewPage, $mTitle;
var $mRcidMarkPatrolled;
+
+ /**
+ * @var Revision
+ */
var $mOldRev, $mNewRev;
var $mRevisionsLoaded = false; // Have the revisions been loaded
var $mTextLoaded = 0; // How many text blobs have been loaded, 0, 1 or 2?
@@ -49,9 +57,9 @@ class DifferenceEngine {
/**
* Constructor
* @param $titleObj Title object that the diff is associated with
- * @param $old Integer: old ID we want to show and diff with.
- * @param $new String: either 'prev' or 'next'.
- * @param $rcid Integer: ??? FIXME (default 0)
+ * @param $old Integer old ID we want to show and diff with.
+ * @param $new String either 'prev' or 'next'.
+ * @param $rcid Integer ??? FIXME (default 0)
* @param $refreshCache boolean If set, refreshes the diff cache
* @param $unhide boolean If set, allow viewing deleted revs
*/
@@ -62,7 +70,7 @@ class DifferenceEngine {
$this->mTitle = $titleObj;
} else {
global $wgTitle;
- $this->mTitle = $wgTitle;
+ $this->mTitle = $wgTitle; // @TODO: get rid of this
}
wfDebug( "DifferenceEngine old '$old' new '$new' rcid '$rcid'\n" );
@@ -91,26 +99,82 @@ class DifferenceEngine {
$this->unhide = $unhide;
}
+ /**
+ * @param $value bool
+ */
function setReducedLineNumbers( $value = true ) {
$this->mReducedLineNumbers = $value;
}
+ /**
+ * @return Title
+ */
function getTitle() {
return $this->mTitle;
}
+ /**
+ * @return bool
+ */
function wasCacheHit() {
return $this->mCacheHit;
}
+ /**
+ * @return int
+ */
function getOldid() {
return $this->mOldid;
}
+ /**
+ * @return Bool|int
+ */
function getNewid() {
return $this->mNewid;
}
+ /**
+ * Look up a special:Undelete link to the given deleted revision id,
+ * as a workaround for being unable to load deleted diffs in currently.
+ *
+ * @param int $id revision ID
+ * @return mixed URL or false
+ */
+ function deletedLink( $id ) {
+ global $wgUser;
+ if ( $wgUser->isAllowed( 'deletedhistory' ) ) {
+ $dbr = wfGetDB( DB_SLAVE );
+ $row = $dbr->selectRow('archive', '*',
+ array( 'ar_rev_id' => $id ),
+ __METHOD__ );
+ if ( $row ) {
+ $rev = Revision::newFromArchiveRow( $row );
+ $title = Title::makeTitleSafe( $row->ar_namespace, $row->ar_title );
+ return SpecialPage::getTitleFor( 'Undelete' )->getFullURL( array(
+ 'target' => $title->getPrefixedText(),
+ 'timestamp' => $rev->getTimestamp()
+ ));
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Build a wikitext link toward a deleted revision, if viewable.
+ *
+ * @param int $id revision ID
+ * @return string wikitext fragment
+ */
+ function deletedIdMarker( $id ) {
+ $link = $this->deletedLink( $id );
+ if ( $link ) {
+ return "[$link $id]";
+ } else {
+ return $id;
+ }
+ }
+
function showDiffPage( $diffOnly = false ) {
global $wgUser, $wgOut, $wgUseExternalEditor, $wgUseRCPatrol;
wfProfileIn( __METHOD__ );
@@ -122,14 +186,14 @@ class DifferenceEngine {
# we'll use the application/x-external-editor interface to call
# an external diff tool like kompare, kdiff3, etc.
if ( $wgUseExternalEditor && $wgUser->getOption( 'externaldiff' ) ) {
- global $wgInputEncoding, $wgServer, $wgScript, $wgLang;
+ global $wgCanonicalServer, $wgScript, $wgLang;
$wgOut->disable();
- header ( "Content-type: application/x-external-editor; charset=" . $wgInputEncoding );
- $url1 = $this->mTitle->getFullURL( array(
+ header ( "Content-type: application/x-external-editor; charset=UTF-8" );
+ $url1 = $this->mTitle->getCanonical( array(
'action' => 'raw',
'oldid' => $this->mOldid
) );
- $url2 = $this->mTitle->getFullURL( array(
+ $url2 = $this->mTitle->getCanonical( array(
'action' => 'raw',
'oldid' => $this->mNewid
) );
@@ -138,7 +202,7 @@ class DifferenceEngine {
[Process]
Type=Diff text
Engine=MediaWiki
- Script={$wgServer}{$wgScript}
+ Script={$wgCanonicalServer}{$wgScript}
Special namespace={$special}
[File]
@@ -157,10 +221,13 @@ CONTROL;
$wgOut->setArticleFlag( false );
if ( !$this->loadRevisionData() ) {
+ // Sounds like a deleted revision... Let's see what we can do.
$t = $this->mTitle->getPrefixedText();
- $d = wfMsgExt( 'missingarticle-diff', array( 'escape' ), $this->mOldid, $this->mNewid );
+ $d = wfMsgExt( 'missingarticle-diff', array( 'escape' ),
+ $this->deletedIdMarker( $this->mOldid ),
+ $this->deletedIdMarker( $this->mNewid ) );
$wgOut->setPagetitle( wfMsg( 'errorpagetitle' ) );
- $wgOut->addWikiMsg( 'missing-article', "<nowiki>$t</nowiki>", $d );
+ $wgOut->addWikiMsg( 'missing-article', "<nowiki>$t</nowiki>", "<span class='plainlinks'>$d</span>" );
wfProfileOut( __METHOD__ );
return;
}
@@ -181,8 +248,6 @@ CONTROL;
return;
}
- $wgOut->suppressQuickbar();
-
$oldTitle = $this->mOldPage->getPrefixedText();
$newTitle = $this->mNewPage->getPrefixedText();
if ( $oldTitle == $newTitle ) {
@@ -206,6 +271,9 @@ CONTROL;
}
$sk = $wgUser->getSkin();
+ if ( method_exists( $sk, 'suppressQuickbar' ) ) {
+ $sk->suppressQuickbar();
+ }
// Check if page is editable
$editable = $this->mNewRev->getTitle()->userCan( 'edit' );
@@ -372,7 +440,7 @@ CONTROL;
if ( !$allowed ) {
$msg = $suppressed ? 'rev-suppressed-no-diff' : 'rev-deleted-no-diff';
# Give explanation for why revision is not visible
- $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n",
+ $wgOut->wrapWikiMsg( "<div id='mw-$msg' class='mw-warning plainlinks'>\n$1\n</div>\n",
array( $msg ) );
} else {
# Give explanation and add a link to view the diff...
@@ -382,7 +450,7 @@ CONTROL;
'unhide' => 1
) );
$msg = $suppressed ? 'rev-suppressed-unhide-diff' : 'rev-deleted-unhide-diff';
- $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", array( $msg, $link ) );
+ $wgOut->wrapWikiMsg( "<div id='mw-$msg' class='mw-warning plainlinks'>\n$1\n</div>\n", array( $msg, $link ) );
}
# Otherwise, output a regular diff...
} else {
@@ -390,7 +458,7 @@ CONTROL;
$notice = '';
if ( $deleted ) {
$msg = $suppressed ? 'rev-suppressed-diff-view' : 'rev-deleted-diff-view';
- $notice = "<div class='mw-warning plainlinks'>\n" . wfMsgExt( $msg, 'parseinline' ) . "</div>\n";
+ $notice = "<div id='mw-$msg' class='mw-warning plainlinks'>\n" . wfMsgExt( $msg, 'parseinline' ) . "</div>\n";
}
$this->showDiff( $oldHeader, $newHeader, $notice );
if ( !$diffOnly ) {
@@ -400,6 +468,10 @@ CONTROL;
wfProfileOut( __METHOD__ );
}
+ /**
+ * @param $rev Revision
+ * @return String
+ */
protected function revisionDeleteLink( $rev ) {
global $wgUser;
$link = '';
@@ -431,42 +503,37 @@ CONTROL;
function renderNewRevision() {
global $wgOut, $wgUser;
wfProfileIn( __METHOD__ );
+ # Add "current version as of X" title
+ $wgOut->addHTML( "<hr class='diff-hr' />
+ <h2 class='diff-currentversion-title'>{$this->mPagetitle}</h2>\n" );
+ # Page content may be handled by a hooked call instead...
+ if ( wfRunHooks( 'ArticleContentOnDiff', array( $this, $wgOut ) ) ) {
+ # Use the current version parser cache if applicable
+ $pCache = true;
+ if ( !$this->mNewRev->isCurrent() ) {
+ $oldEditSectionSetting = $wgOut->parserOptions()->setEditSection( false );
+ $pCache = false;
+ }
- $wgOut->addHTML( "<hr /><h2>{$this->mPagetitle}</h2>\n" );
- # Add deleted rev tag if needed
- if ( !$this->mNewRev->userCan( Revision::DELETED_TEXT ) ) {
- $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-permission' );
- } else if ( $this->mNewRev->isDeleted( Revision::DELETED_TEXT ) ) {
- $wgOut->wrapWikiMsg( "<div class='mw-warning plainlinks'>\n$1\n</div>\n", 'rev-deleted-text-view' );
- }
-
- $pCache = true;
- if ( !$this->mNewRev->isCurrent() ) {
- $oldEditSectionSetting = $wgOut->parserOptions()->setEditSection( false );
- $pCache = false;
- }
-
- $this->loadNewText();
- if ( is_object( $this->mNewRev ) ) {
+ $this->loadNewText();
$wgOut->setRevisionId( $this->mNewRev->getId() );
- }
- if ( $this->mTitle->isCssJsSubpage() || $this->mTitle->isCssOrJsPage() ) {
- // Stolen from Article::view --AG 2007-10-11
- // Give hooks a chance to customise the output
- if ( wfRunHooks( 'ShowRawCssJs', array( $this->mNewtext, $this->mTitle, $wgOut ) ) ) {
- // Wrap the whole lot in a <pre> and don't parse
- $m = array();
- preg_match( '!\.(css|js)$!u', $this->mTitle->getText(), $m );
- $wgOut->addHTML( "<pre class=\"mw-code mw-{$m[1]}\" dir=\"ltr\">\n" );
- $wgOut->addHTML( htmlspecialchars( $this->mNewtext ) );
- $wgOut->addHTML( "\n</pre>\n" );
- }
- } elseif ( wfRunHooks( 'ArticleContentOnDiff', array( $this, $wgOut ) ) ) {
- if ( $pCache ) {
+ if ( $this->mTitle->isCssJsSubpage() || $this->mTitle->isCssOrJsPage() ) {
+ // Stolen from Article::view --AG 2007-10-11
+ // Give hooks a chance to customise the output
+ // @TODO: standardize this crap into one function
+ if ( wfRunHooks( 'ShowRawCssJs', array( $this->mNewtext, $this->mTitle, $wgOut ) ) ) {
+ // Wrap the whole lot in a <pre> and don't parse
+ $m = array();
+ preg_match( '!\.(css|js)$!u', $this->mTitle->getText(), $m );
+ $wgOut->addHTML( "<pre class=\"mw-code mw-{$m[1]}\" dir=\"ltr\">\n" );
+ $wgOut->addHTML( htmlspecialchars( $this->mNewtext ) );
+ $wgOut->addHTML( "\n</pre>\n" );
+ }
+ } elseif ( $pCache ) {
$article = new Article( $this->mTitle, 0 );
$pOutput = ParserCache::singleton()->get( $article, $wgOut->parserOptions() );
- if ( $pOutput ) {
+ if( $pOutput ) {
$wgOut->addParserOutput( $pOutput );
} else {
$article->doViewParse();
@@ -474,12 +541,11 @@ CONTROL;
} else {
$wgOut->addWikiTextTidy( $this->mNewtext );
}
- }
- if ( is_object( $this->mNewRev ) && !$this->mNewRev->isCurrent() ) {
- $wgOut->parserOptions()->setEditSection( $oldEditSectionSetting );
+ if ( !$this->mNewRev->isCurrent() ) {
+ $wgOut->parserOptions()->setEditSection( $oldEditSectionSetting );
+ }
}
-
# Add redundant patrol link on bottom...
if ( $this->mRcidMarkPatrolled && $this->mTitle->quickUserCan( 'patrol' ) ) {
$sk = $wgUser->getSkin();
@@ -491,9 +557,9 @@ CONTROL;
wfMsgHtml( 'markaspatrolleddiff' ),
array(),
array(
- 'action' => 'markpatrolled',
- 'rcid' => $this->mRcidMarkPatrolled,
- 'token' => $token,
+ 'action' => 'markpatrolled',
+ 'rcid' => $this->mRcidMarkPatrolled,
+ 'token' => $token,
)
) . ']</div>'
);
@@ -514,9 +580,11 @@ CONTROL;
#
if ( ! $this->loadNewText() ) {
$t = $this->mTitle->getPrefixedText();
- $d = wfMsgExt( 'missingarticle-diff', array( 'escape' ), $this->mOldid, $this->mNewid );
+ $d = wfMsgExt( 'missingarticle-diff', array( 'escape' ),
+ $this->deletedIdMarker( $this->mOldid ),
+ $this->deletedIdMarker( $this->mNewid ) );
$wgOut->setPagetitle( wfMsg( 'errorpagetitle' ) );
- $wgOut->addWikiMsg( 'missing-article', "<nowiki>$t</nowiki>", $d );
+ $wgOut->addWikiMsg( 'missing-article', "<nowiki>$t</nowiki>", "<span class='plainlinks'>$d</span>" );
wfProfileOut( __METHOD__ );
return;
}
@@ -571,6 +639,8 @@ CONTROL;
/**
* Get the diff text, send it to $wgOut
* Returns false if the diff could not be generated, otherwise returns true
+ *
+ * @return bool
*/
function showDiff( $otitle, $ntitle, $notice = '' ) {
global $wgOut;
@@ -590,8 +660,7 @@ CONTROL;
*/
function showDiffStyle() {
global $wgOut;
- $wgOut->addModuleStyles( 'mediawiki.legacy.diff' );
- $wgOut->addModuleScripts( 'mediawiki.legacy.diff' );
+ $wgOut->addModuleStyles( 'mediawiki.action.history.diff' );
}
/**
@@ -691,16 +760,12 @@ CONTROL;
global $wgExternalDiffEngine;
if ( $wgExternalDiffEngine == 'wikidiff' && !function_exists( 'wikidiff_do_diff' ) ) {
wfProfileIn( __METHOD__ . '-php_wikidiff.so' );
- wfSuppressWarnings();
- dl( 'php_wikidiff.so' );
- wfRestoreWarnings();
+ wfDl( 'php_wikidiff' );
wfProfileOut( __METHOD__ . '-php_wikidiff.so' );
}
- else if ( $wgExternalDiffEngine == 'wikidiff2' && !function_exists( 'wikidiff2_do_diff' ) ) {
+ elseif ( $wgExternalDiffEngine == 'wikidiff2' && !function_exists( 'wikidiff2_do_diff' ) ) {
wfProfileIn( __METHOD__ . '-php_wikidiff2.so' );
- wfSuppressWarnings();
wfDl( 'wikidiff2' );
- wfRestoreWarnings();
wfProfileOut( __METHOD__ . '-php_wikidiff2.so' );
}
}
@@ -714,6 +779,8 @@ CONTROL;
function generateDiffBody( $otext, $ntext ) {
global $wgExternalDiffEngine, $wgContLang;
+ wfProfileIn( __METHOD__ );
+
$otext = str_replace( "\r\n", "\n", $otext );
$ntext = str_replace( "\r\n", "\n", $ntext );
@@ -724,6 +791,7 @@ CONTROL;
# input text to be HTML-escaped already
$otext = htmlspecialchars ( $wgContLang->segmentForDiff( $otext ) );
$ntext = htmlspecialchars ( $wgContLang->segmentForDiff( $ntext ) );
+ wfProfileOut( __METHOD__ );
return $wgContLang->unsegmentForDiff( wikidiff_do_diff( $otext, $ntext, 2 ) ) .
$this->debug( 'wikidiff1' );
}
@@ -735,6 +803,7 @@ CONTROL;
$text = wikidiff2_do_diff( $otext, $ntext, 2 );
$text .= $this->debug( 'wikidiff2' );
wfProfileOut( 'wikidiff2_do_diff' );
+ wfProfileOut( __METHOD__ );
return $text;
}
if ( $wgExternalDiffEngine != 'wikidiff3' && $wgExternalDiffEngine !== false ) {
@@ -776,7 +845,6 @@ CONTROL;
$difftext = $wgContLang->unsegmentForDiff( $formatter->format( $diffs ) ) .
wfProfileOut( __METHOD__ );
return $difftext;
- $this->debug();
}
/**
@@ -828,18 +896,18 @@ CONTROL;
return '';
}
- $oldid = $this->mOldRev->getId();
- $newid = $this->mNewRev->getId();
- if ( $oldid > $newid ) {
- $tmp = $oldid; $oldid = $newid; $newid = $tmp;
+ if ( $this->mOldRev->getTimestamp() > $this->mNewRev->getTimestamp() ) {
+ $oldRev = $this->mNewRev; // flip
+ $newRev = $this->mOldRev; // flip
+ } else { // normal case
+ $oldRev = $this->mOldRev;
+ $newRev = $this->mNewRev;
}
- $nEdits = $this->mTitle->countRevisionsBetween( $oldid, $newid );
+ $nEdits = $this->mTitle->countRevisionsBetween( $oldRev, $newRev );
if ( $nEdits > 0 ) {
- $limit = 100;
- // We use ($limit + 1) so we can detect if there are > 100 authors
- // in a given revision range. In that case, diff-multi-manyusers is used.
- $numUsers = $this->mTitle->countAuthorsBetween( $oldid, $newid, $limit + 1 );
+ $limit = 100; // use diff-multi-manyusers if too many users
+ $numUsers = $this->mTitle->countAuthorsBetween( $oldRev, $newRev, $limit );
return self::intermediateEditsMsg( $nEdits, $numUsers, $limit );
}
return ''; // nothing
@@ -866,9 +934,15 @@ CONTROL;
/**
* Add the header to a diff body
+ *
+ * @return string
*/
- static function addHeader( $diff, $otitle, $ntitle, $multi = '', $notice = '' ) {
- $header = "<table class='diff'>";
+ function addHeader( $diff, $otitle, $ntitle, $multi = '', $notice = '' ) {
+ // shared.css sets diff in interface language/dir,
+ // but the actual content should be in the page language/dir
+ $pageLang = $this->mTitle->getPageLanguage();
+ $tableClass = 'diff diff-contentalign-' . htmlspecialchars( $pageLang->alignStart() );
+ $header = "<table class='$tableClass'>";
if ( $diff ) { // Safari/Chrome show broken output if cols not used
$header .= "
<col class='diff-marker' />
@@ -916,6 +990,8 @@ CONTROL;
* If oldid is false, leave the corresponding revision object set
* to false. This is impossible via ordinary user input, and is provided for
* API convenience.
+ *
+ * @return bool
*/
function loadRevisionData() {
global $wgLang, $wgUser;
@@ -930,8 +1006,9 @@ CONTROL;
$this->mNewRev = $this->mNewid
? Revision::newFromId( $this->mNewid )
: Revision::newFromTitle( $this->mTitle );
- if ( !$this->mNewRev instanceof Revision )
+ if ( !$this->mNewRev instanceof Revision ) {
return false;
+ }
// Update the new revision ID in case it was 0 (makes life easier doing UI stuff)
$this->mNewid = $this->mNewRev->getId();
@@ -980,7 +1057,7 @@ CONTROL;
}
if ( !$this->mNewRev->userCan( Revision::DELETED_TEXT ) ) {
$this->mNewtitle = "<span class='history-deleted'>{$this->mPagetitle}</span>";
- } else if ( $this->mNewRev->isDeleted( Revision::DELETED_TEXT ) ) {
+ } elseif ( $this->mNewRev->isDeleted( Revision::DELETED_TEXT ) ) {
$this->mNewtitle = "<span class='history-deleted'>{$this->mNewtitle}</span>";
}
@@ -1022,20 +1099,20 @@ CONTROL;
$this->mOldtitle = "<a href='$oldLink'>{$this->mOldPagetitle}</a>"
. " (<a href='$oldEdit'>" . wfMsgHtml( $editable ? 'editold' : 'viewsourceold' ) . "</a>)";
// Add an "undo" link
- $newUndo = $this->mNewPage->escapeLocalUrl( array(
- 'action' => 'edit',
- 'undoafter' => $this->mOldid,
- 'undo' => $this->mNewid
- ) );
- $htmlLink = htmlspecialchars( wfMsg( 'editundo' ) );
- $htmlTitle = Xml::expandAttributes( array( 'title' => $wgUser->getSkin()->titleAttrib( 'undo' ) ) );
if ( $editable && !$this->mOldRev->isDeleted( Revision::DELETED_TEXT ) && !$this->mNewRev->isDeleted( Revision::DELETED_TEXT ) ) {
- $this->mNewtitle .= " (<a href='$newUndo' $htmlTitle>" . $htmlLink . "</a>)";
+ $undoLink = Html::element( 'a', array(
+ 'href' => $this->mNewPage->getLocalUrl( array(
+ 'action' => 'edit',
+ 'undoafter' => $this->mOldid,
+ 'undo' => $this->mNewid ) ),
+ 'title' => $wgUser->getSkin()->titleAttrib( 'undo' )
+ ), wfMsg( 'editundo' ) );
+ $this->mNewtitle .= ' (' . $undoLink . ')';
}
if ( !$this->mOldRev->userCan( Revision::DELETED_TEXT ) ) {
$this->mOldtitle = '<span class="history-deleted">' . $this->mOldPagetitle . '</span>';
- } else if ( $this->mOldRev->isDeleted( Revision::DELETED_TEXT ) ) {
+ } elseif ( $this->mOldRev->isDeleted( Revision::DELETED_TEXT ) ) {
$this->mOldtitle = '<span class="history-deleted">' . $this->mOldtitle . '</span>';
}
}
@@ -1045,6 +1122,8 @@ CONTROL;
/**
* Load the text of the revisions, as well as revision data.
+ *
+ * @return bool
*/
function loadText() {
if ( $this->mTextLoaded == 2 ) {
@@ -1074,6 +1153,8 @@ CONTROL;
/**
* Load the text of the new revision, not the old one
+ *
+ * @return bool
*/
function loadNewText() {
if ( $this->mTextLoaded >= 1 ) {
diff --git a/includes/diff/WikiDiff3.php b/includes/diff/WikiDiff3.php
index 8def296d..27d3d5b8 100644
--- a/includes/diff/WikiDiff3.php
+++ b/includes/diff/WikiDiff3.php
@@ -239,7 +239,7 @@ class WikiDiff3 {
$starty - 1, $V, $snake )
+ $this->lcs_rec( $startx + $len, $topl1, $starty + $len,
$topl2, $V, $snake );
- } else if ( $d == 1 ) {
+ } elseif ( $d == 1 ) {
/*
* In this case the sequences differ by exactly 1 line. We have
* already saved all the lines after the difference in the for loop
@@ -332,7 +332,7 @@ class WikiDiff3 {
// check to see if we can cut down the diagonal range
if ( $x >= $N && $end_forward > $k - 1 ) {
$end_forward = $k - 1;
- } else if ( $absy - $bottoml2 >= $M ) {
+ } elseif ( $absy - $bottoml2 >= $M ) {
$start_forward = $k + 1;
$value_to_add_forward = 0;
}
@@ -366,7 +366,7 @@ class WikiDiff3 {
if ( $x <= 0 ) {
$start_backward = $k + 1;
$value_to_add_backward = 0;
- } else if ( $y <= 0 && $end_backward > $k - 1 ) {
+ } elseif ( $y <= 0 && $end_backward > $k - 1 ) {
$end_backward = $k - 1;
}
}
@@ -400,7 +400,7 @@ class WikiDiff3 {
// check to see if we can cut down the diagonal range
if ( $x >= $N && $end_forward > $k - 1 ) {
$end_forward = $k - 1;
- } else if ( $absy -$bottoml2 >= $M ) {
+ } elseif ( $absy -$bottoml2 >= $M ) {
$start_forward = $k + 1;
$value_to_add_forward = 0;
}
@@ -441,7 +441,7 @@ class WikiDiff3 {
if ( $x <= 0 ) {
$start_backward = $k + 1;
$value_to_add_backward = 0;
- } else if ( $y <= 0 && $end_backward > $k - 1 ) {
+ } elseif ( $y <= 0 && $end_backward > $k - 1 ) {
$end_backward = $k - 1;
}
}
@@ -510,7 +510,7 @@ class WikiDiff3 {
$max_progress[0][0] = $x;
$max_progress[0][1] = $y;
$max_progress[0][2] = $progress;
- } else if ( $progress == $max_progress[0][2] ) {
+ } elseif ( $progress == $max_progress[0][2] ) {
++$num_progress;
$max_progress[$num_progress][0] = $x;
$max_progress[$num_progress][1] = $y;
@@ -537,7 +537,7 @@ class WikiDiff3 {
$max_progress[0][0] = $x;
$max_progress[0][1] = $y;
$max_progress[0][2] = $progress;
- } else if ( $progress == $max_progress[0][2] && !$max_progress_forward ) {
+ } elseif ( $progress == $max_progress[0][2] && !$max_progress_forward ) {
++$num_progress;
$max_progress[$num_progress][0] = $x;
$max_progress[$num_progress][1] = $y;