-<?
+<?php
# See diff.doc
class DifferenceEngine {
/* private */ var $mOldid, $mNewid;
/* private */ var $mOldtitle, $mNewtitle;
/* private */ var $mOldtext, $mNewtext;
-
+ /* private */ var $mOldUser, $mNewUser;
+
function DifferenceEngine( $old, $new )
{
$this->mOldid = $old;
$wgOut->addHTML( $mtext );
return;
}
- $wgOut->supressQuickbar();
+ $wgOut->suppressQuickbar();
$wgOut->setSubtitle( wfMsg( "difference" ) );
$wgOut->setRobotpolicy( "noindex,follow" );
+
+ $sk = $wgUser->getSkin();
+ $talk = $wgLang->getNsText( NS_TALK );
+ $contribs = wfMsg( "contribslink" );
+
+ $oldUserLink = $sk->makeLinkObj( Title::makeTitle( NS_USER, $this->mOldUser ), $this->mOldUser );
+ $newUserLink = $sk->makeLinkObj( Title::makeTitle( NS_USER, $this->mNewUser ), $this->mNewUser );
+ $oldUTLink = $sk->makeLinkObj( Title::makeTitle( NS_USER_TALK, $this->mOldUser ), $talk );
+ $newUTLink = $sk->makeLinkObj( Title::makeTitle( NS_USER_TALK, $this->mNewUser ), $talk );
+ $oldContribs = $sk->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, "Contributions" ), $contribs,
+ "target=" . urlencode($this->mOldUser) );
+ $newContribs = $sk->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, "Contributions" ), $contribs,
+ "target=" . urlencode($this->mNewUser) );
+ if ( !$this->mNewid && $wgUser->isSysop() ) {
+ $rollback = " <strong>[" . $sk->makeKnownLinkObj( $wgTitle, wfMsg( "rollbacklink" ),
+ "action=rollback&from=" . urlencode($this->mNewUser) ) . "]</strong>";
+ } else {
+ $rollback = "";
+ }
+
+ $oldHeader = "<strong>{$this->mOldtitle}</strong><br>$oldUserLink ($oldUTLink | $oldContribs)";
+ $newHeader = "<strong>{$this->mNewtitle}</strong><br>$newUserLink ($newUTLink | $newContribs) $rollback";
DifferenceEngine::showDiff( $this->mOldtext, $this->mNewtext,
- $this->mOldtitle, $this->mNewtitle );
+ $oldHeader, $newHeader );
$wgOut->addHTML( "<hr><h2>{$this->mNewtitle}</h2>\n" );
$wgOut->addWikiText( $this->mNewtext );
}
$nta = explode( "\n", str_replace( "\r\n", "\n",
htmlspecialchars( $ntext ) ) );
- $wgOut->addHTML( "<table width='98%' border=0
-cellpadding=0 cellspacing='4px'><tr>
+ $wgOut->addHTML( "<table border=0
+cellpadding=0 cellspacing='4px' class='special'><tr>
<td colspan=2 width='50%' align=center bgcolor='#cccccc'>
-<strong>{$otitle}</strong></td>
+{$otitle}</td>
<td colspan=2 width='50%' align=center bgcolor='#cccccc'>
-<strong>{$ntitle}</strong></td>
+{$ntitle}</td>
</tr>\n" );
$diffs = new Diff( $ota, $nta );
{
global $wgTitle, $wgOut, $wgLang;
$fname = "DifferenceEngine::loadText";
-
+
if ( 0 == $this->mNewid || 0 == $this->mOldid ) {
$wgOut->setArticleFlag( true );
$this->mNewtitle = wfMsg( "currentrev" );
$id = $wgTitle->getArticleID();
-
- $sql = "SELECT cur_text FROM cur WHERE cur_id={$id}";
+
+ $sql = "SELECT cur_text, cur_user_text FROM cur WHERE cur_id={$id}";
$res = wfQuery( $sql, DB_READ, $fname );
if ( 0 == wfNumRows( $res ) ) { return false; }
$s = wfFetchObject( $res );
$this->mNewtext = $s->cur_text;
+ $this->mNewUser = $s->cur_user_text;
} else {
- $sql = "SELECT old_timestamp,old_text FROM old WHERE " .
+ $sql = "SELECT old_timestamp,old_text,old_flags,old_user_text FROM old WHERE " .
"old_id={$this->mNewid}";
$res = wfQuery( $sql, DB_READ, $fname );
if ( 0 == wfNumRows( $res ) ) { return false; }
$s = wfFetchObject( $res );
- $this->mNewtext = $s->old_text;
+ $this->mNewtext = Article::getRevisionText( $s );
$t = $wgLang->timeanddate( $s->old_timestamp, true );
$this->mNewtitle = wfMsg( "revisionasof", $t );
+ $this->mNewUser = $s->old_user_text;
}
if ( 0 == $this->mOldid ) {
- $sql = "SELECT old_timestamp,old_text FROM old USE INDEX (name_title_timestamp) WHERE " .
+ $sql = "SELECT old_timestamp,old_text,old_flags,old_user_text " .
+ "FROM old USE INDEX (name_title_timestamp) WHERE " .
"old_namespace=" . $wgTitle->getNamespace() . " AND " .
"old_title='" . wfStrencode( $wgTitle->getDBkey() ) .
"' ORDER BY inverse_timestamp LIMIT 1";
$res = wfQuery( $sql, DB_READ, $fname );
} else {
- $sql = "SELECT old_timestamp,old_text FROM old WHERE " .
+ $sql = "SELECT old_timestamp,old_text,old_flags,old_user_text FROM old WHERE " .
"old_id={$this->mOldid}";
$res = wfQuery( $sql, DB_READ, $fname );
}
if ( 0 == wfNumRows( $res ) ) { return false; }
$s = wfFetchObject( $res );
- $this->mOldtext = $s->old_text;
+ $this->mOldtext = Article::getRevisionText( $s );
$t = $wgLang->timeanddate( $s->old_timestamp, true );
$this->mOldtitle = wfMsg( "revisionasof", $t );
-
+ $this->mOldUser = $s->old_user_text;
+
return true;
}
}
class _DiffOp {
var $type;
var $orig;
- var $final;
+ var $closing;
function reverse() {
trigger_error("pure virtual", E_USER_ERROR);
return $this->orig ? sizeof($this->orig) : 0;
}
- function nfinal() {
- return $this->final ? sizeof($this->final) : 0;
+ function nclosing() {
+ return $this->closing ? sizeof($this->closing) : 0;
}
}
class _DiffOp_Copy extends _DiffOp {
var $type = 'copy';
- function _DiffOp_Copy ($orig, $final = false) {
- if (!is_array($final))
- $final = $orig;
+ function _DiffOp_Copy ($orig, $closing = false) {
+ if (!is_array($closing))
+ $closing = $orig;
$this->orig = $orig;
- $this->final = $final;
+ $this->closing = $closing;
}
function reverse() {
- return new _DiffOp_Copy($this->final, $this->orig);
+ return new _DiffOp_Copy($this->closing, $this->orig);
}
}
function _DiffOp_Delete ($lines) {
$this->orig = $lines;
- $this->final = false;
+ $this->closing = false;
}
function reverse() {
var $type = 'add';
function _DiffOp_Add ($lines) {
- $this->final = $lines;
+ $this->closing = $lines;
$this->orig = false;
}
function reverse() {
- return new _DiffOp_Delete($this->final);
+ return new _DiffOp_Delete($this->closing);
}
}
class _DiffOp_Change extends _DiffOp {
var $type = 'change';
- function _DiffOp_Change ($orig, $final) {
+ function _DiffOp_Change ($orig, $closing) {
$this->orig = $orig;
- $this->final = $final;
+ $this->closing = $closing;
}
function reverse() {
- return new _DiffOp_Change($this->final, $this->orig);
+ return new _DiffOp_Change($this->closing, $this->orig);
}
}
* diffutils-2.7, which can be found at:
* ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz
*
- * Finally, some ideas (subdivision by NCHUNKS > 2, and some optimizations)
+ * closingly, some ideas (subdivision by NCHUNKS > 2, and some optimizations)
* are my own.
*
* @author Geoffrey T. Dairiki
}
/**
- * Get the final set of lines.
+ * Get the closing set of lines.
*
* This reconstructs the $to_lines parameter passed to the
* constructor.
*
* @return array The sequence of strings.
*/
- function final() {
+ function closing() {
$lines = array();
foreach ($this->edits as $edit) {
- if ($edit->final)
- array_splice($lines, sizeof($lines), 0, $edit->final);
+ if ($edit->closing)
+ array_splice($lines, sizeof($lines), 0, $edit->closing);
}
return $lines;
}
function _check ($from_lines, $to_lines) {
if (serialize($from_lines) != serialize($this->orig()))
trigger_error("Reconstructed original doesn't match", E_USER_ERROR);
- if (serialize($to_lines) != serialize($this->final()))
- trigger_error("Reconstructed final 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->final()))
- trigger_error("Reversed final 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';
$xi += sizeof($orig);
}
- $final = &$this->edits[$i]->final;
- if (is_array($final)) {
- $final = array_slice($to_lines, $yi, sizeof($final));
- $yi += sizeof($final);
+ $closing = &$this->edits[$i]->closing;
+ if (is_array($closing)) {
+ $closing = array_slice($to_lines, $yi, sizeof($closing));
+ $yi += sizeof($closing);
}
}
}
if ($edit->orig)
$xi += sizeof($edit->orig);
- if ($edit->final)
- $yi += sizeof($edit->final);
+ if ($edit->closing)
+ $yi += sizeof($edit->closing);
}
if (is_array($block))
if ($edit->type == 'copy')
$this->_context($edit->orig);
elseif ($edit->type == 'add')
- $this->_added($edit->final);
+ $this->_added($edit->closing);
elseif ($edit->type == 'delete')
$this->_deleted($edit->orig);
elseif ($edit->type == 'change')
- $this->_changed($edit->orig, $edit->final);
+ $this->_changed($edit->orig, $edit->closing);
else
trigger_error("Unknown edit type", E_USER_ERROR);
}
$this->_lines($lines, "<");
}
- function _changed($orig, $final) {
+ function _changed($orig, $closing) {
$this->_deleted($orig);
echo "---\n";
- $this->_added($final);
+ $this->_added($closing);
}
}
class WordLevelDiff extends MappedDiff
{
- function WordLevelDiff ($orig_lines, $final_lines) {
+ function WordLevelDiff ($orig_lines, $closing_lines) {
list ($orig_words, $orig_stripped) = $this->_split($orig_lines);
- list ($final_words, $final_stripped) = $this->_split($final_lines);
+ list ($closing_words, $closing_stripped) = $this->_split($closing_lines);
- $this->MappedDiff($orig_words, $final_words,
- $orig_stripped, $final_stripped);
+ $this->MappedDiff($orig_words, $closing_words,
+ $orig_stripped, $closing_stripped);
}
function _split($lines) {
return $orig->getLines();
}
- function final () {
- $final = new _HWLDF_WordAccumulator;
+ function closing () {
+ $closing = new _HWLDF_WordAccumulator;
foreach ($this->edits as $edit) {
if ($edit->type == 'copy')
- $final->addWords($edit->final);
- elseif ($edit->final)
- $final->addWords($edit->final, 'mark');
+ $closing->addWords($edit->closing);
+ elseif ($edit->closing)
+ $closing->addWords($edit->closing, 'mark');
}
- return $final->getLines();
+ return $closing->getLines();
}
}
}
}
- function _changed( $orig, $final ) {
+ function _changed( $orig, $closing ) {
global $wgOut;
- $diff = new WordLevelDiff( $orig, $final );
+ $diff = new WordLevelDiff( $orig, $closing );
$del = $diff->orig();
- $add = $diff->final();
+ $add = $diff->closing();
while ( $line = array_shift( $del ) ) {
$aline = array_shift( $add );