X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FDifferenceEngine.php;h=52bf654d7795b086c249ef8449704f4d61f68017;hb=a91c84bc1c23c2827aa9946036bbdb12e1e01a7e;hp=8b80c27e8b74cecb14d6d8f7210f8f3c7ba0447d;hpb=61c6f0b22368a9edca5c74fc30984f7ac3f8e525;p=lhc%2Fweb%2Fwiklou.git
diff --git a/includes/DifferenceEngine.php b/includes/DifferenceEngine.php
index 8b80c27e8b..52bf654d77 100644
--- a/includes/DifferenceEngine.php
+++ b/includes/DifferenceEngine.php
@@ -1,49 +1,99 @@
mOldid = $old;
- $this->mNewid = $new;
+ global $wgTitle;
+ if ( 'prev' == $new ) {
+ # Show diff between revision $old and the previous one.
+ # Get previous one from DB.
+ #
+ $this->mNewid = intval($old);
+ $dbr =& wfGetDB( DB_SLAVE );
+ $this->mOldid = $dbr->selectField( 'old', 'old_id',
+ "old_title='" . $wgTitle->getDBkey() . "'" .
+ ' AND old_namespace=' . $wgTitle->getNamespace() .
+ " AND old_id<{$this->mNewid} ORDER BY old_id DESC" );
+
+ } elseif ( 'next' == $new ) {
+
+ # Show diff between revision $old and the previous one.
+ # Get previous one from DB.
+ #
+ $this->mOldid = intval($old);
+ $dbr =& wfGetDB( DB_SLAVE );
+ $this->mNewid = $dbr->selectField( 'old', 'old_id',
+ "old_title='" . $wgTitle->getDBkey() . "'" .
+ ' AND old_namespace=' . $wgTitle->getNamespace() .
+ " AND old_id>{$this->mOldid} ORDER BY old_id " );
+ if ( false === $this->mNewid ) {
+ # if no result, NewId points to the newest old revision. The only newer
+ # revision is cur, which is "0".
+ $this->mNewid = 0;
+ }
+
+ } else {
+
+ $this->mOldid = intval($old);
+ $this->mNewid = intval($new);
+ }
+ $this->mRcidMarkPatrolled = intval($rcid); # force it to be an integer
}
function showDiffPage()
{
- global $wgUser, $wgTitle, $wgOut, $wgLang;
- $fname = "DifferenceEngine::showDiffPage";
+ global $wgUser, $wgTitle, $wgOut, $wgLang, $wgOnlySysopsCanPatrol, $wgUseRCPatrol;
+ $fname = 'DifferenceEngine::showDiffPage';
wfProfileIn( $fname );
-
+
+ # mOldid is false if the difference engine is called with a "vague" query for
+ # a diff between a version V and its previous version V' AND the version V
+ # is the first version of that article. In that case, V' does not exist.
+ if ( $this->mOldid === false ) {
+ $this->showFirstRevision();
+ wfProfileOut( $fname );
+ return;
+ }
+
$t = $wgTitle->getPrefixedText() . " (Diff: {$this->mOldid}, " .
"{$this->mNewid})";
- $mtext = wfMsg( "missingarticle", $t );
+ $mtext = wfMsg( 'missingarticle', $t );
$wgOut->setArticleFlag( false );
if ( ! $this->loadText() ) {
- $wgOut->setPagetitle( wfMsg( "errorpagetitle" ) );
+ $wgOut->setPagetitle( wfMsg( 'errorpagetitle' ) );
$wgOut->addHTML( $mtext );
wfProfileOut( $fname );
return;
}
$wgOut->suppressQuickbar();
-
+
$oldTitle = $this->mOldPage->getPrefixedText();
$newTitle = $this->mNewPage->getPrefixedText();
if( $oldTitle == $newTitle ) {
$wgOut->setPageTitle( $newTitle );
} else {
- $wgOut->setPageTitle( $oldTitle . ", " . $newTitle );
+ $wgOut->setPageTitle( $oldTitle . ', ' . $newTitle );
}
- $wgOut->setSubtitle( wfMsg( "difference" ) );
- $wgOut->setRobotpolicy( "noindex,follow" );
-
+ $wgOut->setSubtitle( wfMsg( 'difference' ) );
+ $wgOut->setRobotpolicy( 'noindex,follow' );
+
if ( !( $this->mOldPage->userCanRead() && $this->mNewPage->userCanRead() ) ) {
$wgOut->loginToUse();
$wgOut->output();
@@ -53,38 +103,114 @@ class DifferenceEngine {
$sk = $wgUser->getSkin();
$talk = $wgLang->getNsText( NS_TALK );
- $contribs = wfMsg( "contribslink" );
-
+ $contribs = wfMsg( 'contribslink' );
$this->mOldComment = $sk->formatComment($this->mOldComment);
$this->mNewComment = $sk->formatComment($this->mNewComment);
-
- $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) );
+ $oldUserLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER, $this->mOldUser ), $this->mOldUser );
+ $newUserLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER, $this->mNewUser ), $this->mNewUser );
+ $oldUTLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER_TALK, $this->mOldUser ), $talk );
+ $newUTLink = $sk->makeLinkObj( Title::makeTitleSafe( 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 = " [" . $sk->makeKnownLinkObj( $wgTitle, wfMsg( "rollbacklink" ),
- "action=rollback&from=" . urlencode($this->mNewUser) ) . "]";
+ $rollback = ' [' . $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'rollbacklink' ),
+ 'action=rollback&from=' . urlencode($this->mNewUser) ) . ']';
+ } else {
+ $rollback = '';
+ }
+ if ( $wgUseRCPatrol && $this->mRcidMarkPatrolled != 0 && $wgUser->getID() != 0 &&
+ ( $wgUser->isSysop() || !$wgOnlySysopsCanPatrol ) )
+ {
+ $patrol = ' [' . $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'markaspatrolleddiff' ),
+ "action=markpatrolled&rcid={$this->mRcidMarkPatrolled}" ) . ']';
+ } else {
+ $patrol = '';
+ }
+
+ $prevlink = $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'previousdiff' ), 'diff=prev&oldid='.$this->mOldid );
+ if ( $this->mNewid == 0 ) {
+ $nextlink = '';
} else {
- $rollback = "";
+ $nextlink = $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'nextdiff' ), 'diff=next&oldid='.$this->mNewid );
}
- $oldHeader = "{$this->mOldtitle}
$oldUserLink ($oldUTLink | $oldContribs)
".
- $this->mOldComment;
- $newHeader = "{$this->mNewtitle}
$newUserLink ($newUTLink | $newContribs) $rollback
".
- $this->mNewComment;
+ $oldHeader = "{$this->mOldtitle}
$oldUserLink " .
+ "($oldUTLink | $oldContribs)
" . $this->mOldComment .
+ '
' . $prevlink;
+ $newHeader = "{$this->mNewtitle}
$newUserLink " .
+ "($newUTLink | $newContribs) $rollback
" . $this->mNewComment .
+ '
' . $nextlink . $patrol;
DifferenceEngine::showDiff( $this->mOldtext, $this->mNewtext,
$oldHeader, $newHeader );
- $wgOut->addHTML( "
{$this->mNewtitle}
\n" );
+ $wgOut->addHTML( "
{$this->mPagetitle}
\n" );
$wgOut->addWikiText( $this->mNewtext );
-
+
+ wfProfileOut( $fname );
+ }
+
+ # Show the first revision of an article. Uses normal diff headers in contrast to normal
+ # "old revision" display style.
+ #
+ function showFirstRevision()
+ {
+ global $wgOut, $wgTitle, $wgUser, $wgLang;
+
+ $fname = 'DifferenceEngine::showFirstRevision';
+ wfProfileIn( $fname );
+
+
+ $this->mOldid = $this->mNewid; # hack to make loadText() work.
+
+ # Get article text from the DB
+ #
+ if ( ! $this->loadText() ) {
+ $t = $wgTitle->getPrefixedText() . " (Diff: {$this->mOldid}, " .
+ "{$this->mNewid})";
+ $mtext = wfMsg( 'missingarticle', $t );
+ $wgOut->setPagetitle( wfMsg( 'errorpagetitle' ) );
+ $wgOut->addHTML( $mtext );
+ wfProfileOut( $fname );
+ return;
+ }
+
+ # Check if user is allowed to look at this page. If not, bail out.
+ #
+ if ( !( $this->mOldPage->userCanRead() ) ) {
+ $wgOut->loginToUse();
+ $wgOut->output();
+ wfProfileOut( $fname );
+ exit;
+ }
+
+ # Prepare the header box
+ #
+ $sk = $wgUser->getSkin();
+
+ $uTLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER_TALK, $this->mOldUser ), $wgLang->getNsText( NS_TALK ) );
+ $userLink = $sk->makeLinkObj( Title::makeTitleSafe( NS_USER, $this->mOldUser ), $this->mOldUser );
+ $contribs = $sk->makeKnownLinkObj( Title::makeTitle( NS_SPECIAL, 'Contributions' ), wfMsg( 'contribslink' ),
+ 'target=' . urlencode($this->mOldUser) );
+ $nextlink = $sk->makeKnownLinkObj( $wgTitle, wfMsg( 'nextdiff' ), 'diff=next&oldid='.$this->mNewid );
+ $header = "\n";
+
+ $wgOut->addHTML( $header );
+
+ $wgOut->setSubtitle( wfMsg( 'difference' ) );
+ $wgOut->setRobotpolicy( 'noindex,follow' );
+
+
+ # Show current revision
+ #
+ $wgOut->addHTML( "
{$this->mPagetitle}
\n" );
+ $wgOut->addWikiText( $this->mNewtext );
+
wfProfileOut( $fname );
}
@@ -92,23 +218,24 @@ class DifferenceEngine {
{
global $wgOut, $wgUseExternalDiffEngine;
- $otext = str_replace( "\r\n", "\n", htmlspecialchars( $otext ) );
- $ntext = str_replace( "\r\n", "\n", htmlspecialchars( $ntext ) );
+ $wgOut->addHTML( "
+
+
+ {$otitle} |
+ {$ntitle} |
+
+ " );
-
- $wgOut->addHTML( "
-
-{$otitle} |
-
-{$ntitle} |
-
\n" );
if ( $wgUseExternalDiffEngine ) {
- dl("php_wikidiff.so");
+ # For historical reasons, external diff engine expects
+ # input text to be HTML-escaped already
+ $otext = str_replace( "\r\n", "\n", htmlspecialchars ( $otext ) );
+ $ntext = str_replace( "\r\n", "\n", htmlspecialchars ( $ntext ) );
+ dl('php_wikidiff.so');
$wgOut->addHTML( wikidiff_do_diff( $otext, $ntext, 2) );
} else {
- $ota = explode( "\n", $otext);
- $nta = explode( "\n", $ntext);
+ $ota = explode( "\n", str_replace( "\r\n", "\n", $otext ) );
+ $nta = explode( "\n", str_replace( "\r\n", "\n", $ntext ) );
$diffs = new Diff( $ota, $nta );
$formatter = new TableDiffFormatter();
$formatter->format( $diffs );
@@ -124,18 +251,21 @@ cellpadding='0' cellspacing='4px' class='diff'>
function loadText()
{
global $wgTitle, $wgOut, $wgLang;
- $fname = "DifferenceEngine::loadText";
-
+ $fname = 'DifferenceEngine::loadText';
+
$dbr =& wfGetDB( DB_SLAVE );
if ( 0 == $this->mNewid || 0 == $this->mOldid ) {
$wgOut->setArticleFlag( true );
- $this->mNewtitle = wfMsg( "currentrev" );
+ $newLink = $wgTitle->getLocalUrl();
+ $this->mPagetitle = wfMsg( 'currentrev' );
+ $this->mNewtitle = "{$this->mPagetitle}";
$id = $wgTitle->getArticleID();
-
- $s = $dbr->getArray( 'cur', array( 'cur_text', 'cur_user_text', 'cur_comment' ),
+
+ $s = $dbr->getArray( 'cur', array( 'cur_text', 'cur_user_text', 'cur_comment' ),
array( 'cur_id' => $id ), $fname );
- if ( $s === false ) {
- return false;
+ if ( $s === false ) {
+ wfDebug( "Unable to load cur_id $id\n" );
+ return false;
}
$this->mNewPage = &$wgTitle;
@@ -146,44 +276,53 @@ cellpadding='0' cellspacing='4px' class='diff'>
$s = $dbr->getArray( 'old', array( 'old_namespace','old_title','old_timestamp', 'old_text',
'old_flags','old_user_text','old_comment' ), array( 'old_id' => $this->mNewid ), $fname );
- if ( $s === false ) {
- return false;
+ if ( $s === false ) {
+ wfDebug( "Unable to load old_id {$this->mNewid}\n" );
+ return false;
}
$this->mNewtext = Article::getRevisionText( $s );
$t = $wgLang->timeanddate( $s->old_timestamp, true );
$this->mNewPage = Title::MakeTitle( $s->old_namespace, $s->old_title );
- $this->mNewtitle = wfMsg( "revisionasof", $t );
+ $newLink = $wgTitle->getLocalUrl ('oldid=' . $this->mNewid);
+ $this->mPagetitle = wfMsg( 'revisionasof', $t );
+ $this->mNewtitle = "{$this->mPagetitle}";
$this->mNewUser = $s->old_user_text;
$this->mNewComment = $s->old_comment;
}
if ( 0 == $this->mOldid ) {
- $s = $dbr->getArray( 'old',
- array( 'old_namespace','old_title','old_timestamp','old_text', 'old_flags','old_user_text','old_comment' ),
+ $s = $dbr->getArray( 'old',
+ array( 'old_namespace','old_title','old_timestamp','old_text', 'old_flags','old_user_text','old_comment' ),
array( /* WHERE */
- 'old_namespace' => $this->mNewPage->getNamespace(),
- 'old_title' => $this->mNewPage->getDBkey()
+ 'old_namespace' => $this->mNewPage->getNamespace(),
+ 'old_title' => $this->mNewPage->getDBkey()
), $fname, array( 'ORDER BY' => 'inverse_timestamp', 'USE INDEX' => 'name_title_timestamp' )
);
+ if ( $s === false ) {
+ wfDebug( 'Unable to load ' . $this->mNewPage->getPrefixedDBkey . " from old\n" );
+ return false;
+ }
} else {
- $s = $dbr->getArray( 'old',
+ $s = $dbr->getArray( 'old',
array( 'old_namespace','old_title','old_timestamp','old_text','old_flags','old_user_text','old_comment'),
- array( 'old_id' => $this->mOldid ),
+ array( 'old_id' => $this->mOldid ),
$fname
);
- }
- if ( $s === false ) {
- return false;
+ if ( $s === false ) {
+ wfDebug( "Unable to load old_id {$this->mOldid}\n" );
+ return false;
+ }
}
$this->mOldPage = Title::MakeTitle( $s->old_namespace, $s->old_title );
$this->mOldtext = Article::getRevisionText( $s );
$t = $wgLang->timeanddate( $s->old_timestamp, true );
- $this->mOldtitle = wfMsg( "revisionasof", $t );
+ $oldLink = $this->mOldPage->getLocalUrl ('oldid=' . $this->mOldid);
+ $this->mOldtitle = "" . wfMsg( 'revisionasof', $t ) . '';
$this->mOldUser = $s->old_user_text;
$this->mOldComment = $s->old_comment;
-
+
return true;
}
}
@@ -196,13 +335,17 @@ cellpadding='0' cellspacing='4px' class='diff'>
define('USE_ASSERTS', function_exists('assert'));
+/**
+ * @todo document
+ * @package MediaWiki
+ */
class _DiffOp {
var $type;
var $orig;
var $closing;
-
+
function reverse() {
- trigger_error("pure virtual", E_USER_ERROR);
+ trigger_error('pure virtual', E_USER_ERROR);
}
function norig() {
@@ -214,9 +357,13 @@ class _DiffOp {
}
}
+/**
+ * @todo document
+ * @package MediaWiki
+ */
class _DiffOp_Copy extends _DiffOp {
var $type = 'copy';
-
+
function _DiffOp_Copy ($orig, $closing = false) {
if (!is_array($closing))
$closing = $orig;
@@ -229,9 +376,13 @@ class _DiffOp_Copy extends _DiffOp {
}
}
+/**
+ * @todo document
+ * @package MediaWiki
+ */
class _DiffOp_Delete extends _DiffOp {
var $type = 'delete';
-
+
function _DiffOp_Delete ($lines) {
$this->orig = $lines;
$this->closing = false;
@@ -242,9 +393,13 @@ class _DiffOp_Delete extends _DiffOp {
}
}
+/**
+ * @todo document
+ * @package MediaWiki
+ */
class _DiffOp_Add extends _DiffOp {
var $type = 'add';
-
+
function _DiffOp_Add ($lines) {
$this->closing = $lines;
$this->orig = false;
@@ -255,9 +410,13 @@ class _DiffOp_Add extends _DiffOp {
}
}
+/**
+ * @todo document
+ * @package MediaWiki
+ */
class _DiffOp_Change extends _DiffOp {
var $type = 'change';
-
+
function _DiffOp_Change ($orig, $closing) {
$this->orig = $orig;
$this->closing = $closing;
@@ -267,8 +426,8 @@ class _DiffOp_Change extends _DiffOp {
return new _DiffOp_Change($this->closing, $this->orig);
}
}
-
-
+
+
/**
* Class used internally by Diff to actually compute the diffs.
*
@@ -287,6 +446,7 @@ class _DiffOp_Change extends _DiffOp {
* are my own.
*
* @author Geoffrey T. Dairiki
+ * @package MediaWiki
* @access private
*/
class _DiffEngine
@@ -301,7 +461,7 @@ class _DiffEngine
unset($this->seq);
unset($this->in_seq);
unset($this->lcs);
-
+
// Skip leading common lines.
for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) {
if ($from_lines[$skip] != $to_lines[$skip])
@@ -315,7 +475,7 @@ class _DiffEngine
break;
$this->xchanged[$xi] = $this->ychanged[$yi] = false;
}
-
+
// Ignore lines which do not exist in both files.
for ($xi = $skip; $xi < $n_from - $endskip; $xi++)
$xhash[$from_lines[$xi]] = 1;
@@ -367,7 +527,7 @@ class _DiffEngine
$add = array();
while ($yi < $n_to && $this->ychanged[$yi])
$add[] = $to_lines[$yi++];
-
+
if ($delete && $add)
$edits[] = new _DiffOp_Change($delete, $add);
elseif ($delete)
@@ -377,7 +537,7 @@ class _DiffEngine
}
return $edits;
}
-
+
/* Divide the Largest Common Subsequence (LCS) of the sequences
* [XOFF, XLIM) and [YOFF, YLIM) into NCHUNKS approximately equally
@@ -397,7 +557,7 @@ class _DiffEngine
*/
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.
@@ -417,7 +577,7 @@ class _DiffEngine
$this->seq[0]= $yoff - 1;
$this->in_seq = array();
$ymids[0] = array();
-
+
$numer = $xlim - $xoff + $nchunks - 1;
$x = $xoff;
for ($chunk = 0; $chunk < $nchunks; $chunk++) {
@@ -584,14 +744,14 @@ class _DiffEngine
*/
while ($j < $other_len && $other_changed[$j])
$j++;
-
+
while ($i < $len && ! $changed[$i]) {
USE_ASSERTS && assert('$j < $other_len && ! $other_changed[$j]');
$i++; $j++;
while ($j < $other_len && $other_changed[$j])
$j++;
}
-
+
if ($i == $len)
break;
@@ -672,8 +832,10 @@ class _DiffEngine
/**
* Class representing a 'diff' between two sequences of strings.
+ * @todo document
+ * @package MediaWiki
*/
-class Diff
+class Diff
{
var $edits;
@@ -722,7 +884,7 @@ class Diff
}
return true;
}
-
+
/**
* Compute the length of the Longest Common Subsequence (LCS).
*
@@ -749,7 +911,7 @@ class Diff
*/
function orig() {
$lines = array();
-
+
foreach ($this->edits as $edit) {
if ($edit->orig)
array_splice($lines, sizeof($lines), 0, $edit->orig);
@@ -767,7 +929,7 @@ class Diff
*/
function closing() {
$lines = array();
-
+
foreach ($this->edits as $edit) {
if ($edit->closing)
array_splice($lines, sizeof($lines), 0, $edit->closing);
@@ -776,7 +938,7 @@ class Diff
}
/**
- * Check a Diff for validity.
+ * Check a Diff for validity.
*
* This is here only for debugging purposes.
*/
@@ -801,15 +963,16 @@ class Diff
}
$lcs = $this->lcs();
- trigger_error("Diff okay: LCS = $lcs", E_USER_NOTICE);
+ trigger_error('Diff okay: LCS = '.$lcs, E_USER_NOTICE);
}
}
-
+
/**
* FIXME: bad name.
+ * @todo document
+ * @package MediaWiki
*/
-class MappedDiff
-extends Diff
+class MappedDiff extends Diff
{
/**
* Constructor.
@@ -839,7 +1002,7 @@ extends Diff
assert(sizeof($from_lines) == sizeof($mapped_from_lines));
assert(sizeof($to_lines) == sizeof($mapped_to_lines));
-
+
$this->Diff($mapped_from_lines, $mapped_to_lines);
$xi = $yi = 0;
@@ -849,7 +1012,7 @@ extends Diff
$orig = array_slice($from_lines, $xi, sizeof($orig));
$xi += sizeof($orig);
}
-
+
$closing = &$this->edits[$i]->closing;
if (is_array($closing)) {
$closing = array_slice($to_lines, $yi, sizeof($closing));
@@ -865,6 +1028,8 @@ extends Diff
* This class formats the diff in classic diff format.
* It is intended that this class be customized via inheritance,
* to obtain fancier outputs.
+ * @todo document
+ * @package MediaWiki
*/
class DiffFormatter
{
@@ -958,7 +1123,7 @@ class DiffFormatter
elseif ($edit->type == 'change')
$this->_changed($edit->orig, $edit->closing);
else
- trigger_error("Unknown edit type", E_USER_ERROR);
+ trigger_error('Unknown edit type', E_USER_ERROR);
}
$this->_end_block();
}
@@ -981,11 +1146,11 @@ class DiffFormatter
return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg;
}
-
+
function _start_block($header) {
echo $header;
}
-
+
function _end_block() {
}
@@ -993,16 +1158,16 @@ class DiffFormatter
foreach ($lines as $line)
echo "$prefix $line\n";
}
-
+
function _context($lines) {
$this->_lines($lines);
}
function _added($lines) {
- $this->_lines($lines, ">");
+ $this->_lines($lines, '>');
}
function _deleted($lines) {
- $this->_lines($lines, "<");
+ $this->_lines($lines, '<');
}
function _changed($orig, $closing) {
@@ -1015,11 +1180,15 @@ class DiffFormatter
/**
* Additions by Axel Boldt follow, partly taken from diff.php, phpwiki-1.3.3
- *
+ *
*/
define('NBSP', ' '); // iso-8859-x non-breaking space.
+/**
+ * @todo document
+ * @package MediaWiki
+ */
class _HWLDF_WordAccumulator {
function _HWLDF_WordAccumulator () {
$this->_lines = array();
@@ -1030,22 +1199,26 @@ class _HWLDF_WordAccumulator {
function _flushGroup ($new_tag) {
if ($this->_group !== '') {
- if ($this->_tag == 'mark')
- $this->_line .= ''.$this->_group.'';
- else
- $this->_line .= $this->_group;
- }
+ if ($this->_tag == 'mark')
+ $this->_line .= '' .
+ htmlspecialchars ( $this->_group ) . '';
+ else
+ $this->_line .= htmlspecialchars ( $this->_group );
+ }
$this->_group = '';
$this->_tag = $new_tag;
}
-
+
function _flushLine ($new_tag) {
$this->_flushGroup($new_tag);
if ($this->_line != '')
- $this->_lines[] = $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);
@@ -1055,7 +1228,6 @@ class _HWLDF_WordAccumulator {
if ($word == '')
continue;
if ($word[0] == "\n") {
- $this->_group .= NBSP;
$this->_flushLine($tag);
$word = substr($word, 1);
}
@@ -1070,20 +1242,22 @@ class _HWLDF_WordAccumulator {
}
}
+/**
+ * @todo document
+ * @package MediaWiki
+ */
class WordLevelDiff extends MappedDiff
{
function WordLevelDiff ($orig_lines, $closing_lines) {
list ($orig_words, $orig_stripped) = $this->_split($orig_lines);
list ($closing_words, $closing_stripped) = $this->_split($closing_lines);
-
+
$this->MappedDiff($orig_words, $closing_words,
$orig_stripped, $closing_stripped);
}
function _split($lines) {
- // FIXME: fix POSIX char class.
-# if (!preg_match_all('/ ( [^\S\n]+ | [[:alnum:]]+ | . ) (?: (?!< \n) [^\S\n])? /xs',
if (!preg_match_all('/ ( [^\S\n]+ | [0-9_A-Za-z\x80-\xff]+ | . ) (?: (?!< \n) [^\S\n])? /xs',
implode("\n", $lines),
$m)) {
@@ -1094,7 +1268,7 @@ class WordLevelDiff extends MappedDiff
function orig () {
$orig = new _HWLDF_WordAccumulator;
-
+
foreach ($this->edits as $edit) {
if ($edit->type == 'copy')
$orig->addWords($edit->orig);
@@ -1106,7 +1280,7 @@ class WordLevelDiff extends MappedDiff
function closing () {
$closing = new _HWLDF_WordAccumulator;
-
+
foreach ($this->edits as $edit) {
if ($edit->type == 'copy')
$closing->addWords($edit->closing);
@@ -1119,7 +1293,8 @@ class WordLevelDiff extends MappedDiff
/**
* Wikipedia Table style diff formatter.
- *
+ * @todo document
+ * @package MediaWiki
*/
class TableDiffFormatter extends DiffFormatter
{
@@ -1127,10 +1302,10 @@ class TableDiffFormatter extends DiffFormatter
$this->leading_context_lines = 2;
$this->trailing_context_lines = 2;
}
-
+
function _block_header( $xbeg, $xlen, $ybeg, $ylen ) {
- $l1 = wfMsg( "lineno", $xbeg );
- $l2 = wfMsg( "lineno", $ybeg );
+ $l1 = wfMsg( 'lineno', $xbeg );
+ $l2 = wfMsg( 'lineno', $ybeg );
$r = '
'.$l1." | \n" .
''.$l2." |
\n";
@@ -1145,39 +1320,40 @@ class TableDiffFormatter extends DiffFormatter
function _end_block() {
}
- function _lines( $lines, $prefix=' ', $color="white" ) {
+ function _lines( $lines, $prefix=' ', $color='white' ) {
}
+ # HTML-escape parameter before calling this
function addedLine( $line ) {
- return '+ | ' .
- $line.' | ';
+ return "+ | {$line} | ";
}
+ # HTML-escape parameter before calling this
function deletedLine( $line ) {
- return '- | ' .
- $line.' | ';
+ return "- | {$line} | ";
+ }
+
+ # HTML-escape parameter before calling this
+ function contextLine( $line ) {
+ return " | {$line} | ";
}
function emptyLine() {
return ' | ';
}
- function contextLine( $line ) {
- return ' | '.$line.' | ';
- }
-
- function _added($lines) {
+ function _added( $lines ) {
global $wgOut;
foreach ($lines as $line) {
$wgOut->addHTML( '' . $this->emptyLine() .
- $this->addedLine( $line ) . "
\n" );
+ $this->addedLine( htmlspecialchars ( $line ) ) . "\n" );
}
}
function _deleted($lines) {
global $wgOut;
foreach ($lines as $line) {
- $wgOut->addHTML( '' . $this->deletedLine( $line ) .
+ $wgOut->addHTML( '
' . $this->deletedLine( htmlspecialchars ( $line ) ) .
$this->emptyLine() . "
\n" );
}
}
@@ -1185,8 +1361,9 @@ class TableDiffFormatter extends DiffFormatter
function _context( $lines ) {
global $wgOut;
foreach ($lines as $line) {
- $wgOut->addHTML( '' . $this->contextLine( $line ) .
- $this->contextLine( $line ) . "
\n" );
+ $wgOut->addHTML( '' .
+ $this->contextLine( htmlspecialchars ( $line ) ) .
+ $this->contextLine( htmlspecialchars ( $line ) ) . "
\n" );
}
}
@@ -1196,12 +1373,18 @@ class TableDiffFormatter extends DiffFormatter
$del = $diff->orig();
$add = $diff->closing();
+ # Notice that WordLevelDiff returns HTML-escaped output.
+ # Hence, we will be calling addedLine/deletedLine without HTML-escaping.
+
while ( $line = array_shift( $del ) ) {
$aline = array_shift( $add );
$wgOut->addHTML( '' . $this->deletedLine( $line ) .
- $this->addedLine( $aline ) . "
\n" );
+ $this->addedLine( $aline ) . "\n" );
+ }
+ foreach ($add as $line) { # If any leftovers
+ $wgOut->addHTML( '' . $this->emptyLine() .
+ $this->addedLine( $line ) . "
\n" );
}
- $this->_added( $add ); # If any leftovers
}
}