diff options
author | Pierre Schmitz <pierre@archlinux.de> | 2008-03-21 11:49:34 +0100 |
---|---|---|
committer | Pierre Schmitz <pierre@archlinux.de> | 2008-03-21 11:49:34 +0100 |
commit | 086ae52d12011746a75f5588e877347bc0457352 (patch) | |
tree | e73263c7a29d0f94fafb874562610e16eb292ba8 /includes/DifferenceEngine.php | |
parent | 749e7fb2bae7bbda855de3c9e319435b9f698ff7 (diff) |
Update auf MediaWiki 1.12.0
Diffstat (limited to 'includes/DifferenceEngine.php')
-rw-r--r-- | includes/DifferenceEngine.php | 256 |
1 files changed, 199 insertions, 57 deletions
diff --git a/includes/DifferenceEngine.php b/includes/DifferenceEngine.php index 99bb4798..9aa17bbb 100644 --- a/includes/DifferenceEngine.php +++ b/includes/DifferenceEngine.php @@ -38,8 +38,9 @@ class DifferenceEngine { * @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 */ - function DifferenceEngine( $titleObj = null, $old = 0, $new = 0, $rcid = 0 ) { + function DifferenceEngine( $titleObj = null, $old = 0, $new = 0, $rcid = 0, $refreshCache = false ) { $this->mTitle = $titleObj; wfDebug("DifferenceEngine old '$old' new '$new' rcid '$rcid'\n"); @@ -68,6 +69,7 @@ class DifferenceEngine { $this->mNewid = intval($new); } $this->mRcidMarkPatrolled = intval($rcid); # force it to be an integer + $this->mRefreshCache = $refreshCache; } function showDiffPage( $diffOnly = false ) { @@ -107,9 +109,8 @@ CONTROL; $wgOut->setArticleFlag( false ); if ( ! $this->loadRevisionData() ) { $t = $this->mTitle->getPrefixedText() . " (Diff: {$this->mOldid}, {$this->mNewid})"; - $mtext = wfMsg( 'missingarticle', "<nowiki>$t</nowiki>" ); $wgOut->setPagetitle( wfMsg( 'errorpagetitle' ) ); - $wgOut->addWikitext( $mtext ); + $wgOut->addWikiMsg( 'missingarticle', "<nowiki>$t</nowiki>" ); wfProfileOut( $fname ); return; } @@ -164,14 +165,15 @@ CONTROL; $rcid = $this->mRcidMarkPatrolled; } else { // Look for an unpatrolled change corresponding to this diff + $db = wfGetDB( DB_SLAVE ); $change = RecentChange::newFromConds( array( - // Add redundant timestamp condition so we can use the - // existing index - 'rc_timestamp' => $this->mNewRev->getTimestamp(), + // Add redundant user,timestamp condition so we can use the existing index + 'rc_user_text' => $this->mNewRev->getRawUserText(), + 'rc_timestamp' => $db->timestamp( $this->mNewRev->getTimestamp() ), 'rc_this_oldid' => $this->mNewid, 'rc_last_oldid' => $this->mOldid, - 'rc_patrolled' => 0, + 'rc_patrolled' => 0 ), __METHOD__ ); @@ -217,14 +219,49 @@ CONTROL; $newminor = wfElement( 'span', array( 'class' => 'minor' ), wfMsg( 'minoreditletter') ) . ' '; } + + $rdel = ''; $ldel = ''; + if( $wgUser->isAllowed( 'deleterevision' ) ) { + $revdel = SpecialPage::getTitleFor( 'Revisiondelete' ); + if( !$this->mOldRev->userCan( Revision::DELETED_RESTRICTED ) ) { + // If revision was hidden from sysops + $ldel = wfMsgHtml('rev-delundel'); + } else { + $ldel = $sk->makeKnownLinkObj( $revdel, + wfMsgHtml('rev-delundel'), + 'target=' . urlencode( $this->mOldRev->mTitle->getPrefixedDbkey() ) . + '&oldid=' . urlencode( $this->mOldRev->getId() ) ); + // Bolden oversighted content + if( $this->mOldRev->isDeleted( Revision::DELETED_RESTRICTED ) ) + $ldel = "<strong>$ldel</strong>"; + } + $ldel = " <tt>(<small>$ldel</small>)</tt> "; + // We don't currently handle well changing the top revision's settings + if( $this->mNewRev->isCurrent() ) { + // If revision was hidden from sysops + $rdel = wfMsgHtml('rev-delundel'); + } else if( !$this->mNewRev->userCan( Revision::DELETED_RESTRICTED ) ) { + // If revision was hidden from sysops + $rdel = wfMsgHtml('rev-delundel'); + } else { + $rdel = $sk->makeKnownLinkObj( $revdel, + wfMsgHtml('rev-delundel'), + 'target=' . urlencode( $this->mNewRev->mTitle->getPrefixedDbkey() ) . + '&oldid=' . urlencode( $this->mNewRev->getId() ) ); + // Bolden oversighted content + if( $this->mNewRev->isDeleted( Revision::DELETED_RESTRICTED ) ) + $rdel = "<strong>$rdel</strong>"; + } + $rdel = " <tt>(<small>$rdel</small>)</tt> "; + } - $oldHeader = '<div id="mw-diff-otitle1"><strong>' . $this->mOldtitle . '</strong></div>' . - '<div id="mw-diff-otitle2">' . $sk->revUserTools( $this->mOldRev ) . "</div>" . - '<div id="mw-diff-otitle3">' . $oldminor . $sk->revComment( $this->mOldRev, !$diffOnly ) . "</div>" . - '<div id="mw-diff-otitle4">' . $prevlink . '</div>'; - $newHeader = '<div id="mw-diff-ntitle1"><strong>' .$this->mNewtitle . '</strong></div>' . - '<div id="mw-diff-ntitle2">' . $sk->revUserTools( $this->mNewRev ) . " $rollback</div>" . - '<div id="mw-diff-ntitle3">' . $newminor . $sk->revComment( $this->mNewRev, !$diffOnly ) . "</div>" . + $oldHeader = '<div id="mw-diff-otitle1"><strong>'.$this->mOldtitle.'</strong></div>' . + '<div id="mw-diff-otitle2">' . $sk->revUserTools( $this->mOldRev, true ) . "</div>" . + '<div id="mw-diff-otitle3">' . $oldminor . $sk->revComment( $this->mOldRev, !$diffOnly, true ) . $ldel . "</div>" . + '<div id="mw-diff-otitle4">' . $prevlink .'</div>'; + $newHeader = '<div id="mw-diff-ntitle1"><strong>'.$this->mNewtitle.'</strong></div>' . + '<div id="mw-diff-ntitle2">' . $sk->revUserTools( $this->mNewRev, true ) . " $rollback</div>" . + '<div id="mw-diff-ntitle3">' . $newminor . $sk->revComment( $this->mNewRev, !$diffOnly, true ) . $rdel . "</div>" . '<div id="mw-diff-ntitle4">' . $nextlink . $patrol . '</div>'; $this->showDiff( $oldHeader, $newHeader ); @@ -245,8 +282,10 @@ CONTROL; $wgOut->addHTML( "<hr /><h2>{$this->mPagetitle}</h2>\n" ); #add deleted rev tag if needed - if ( !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) { - $wgOut->addWikiText( wfMsg( 'rev-deleted-text-permission' ) ); + if( !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) { + $wgOut->addWikiMsg( 'rev-deleted-text-permission' ); + } else if( $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) { + $wgOut->addWikiMsg( 'rev-deleted-text-view' ); } if( !$this->mNewRev->isCurrent() ) { @@ -258,7 +297,20 @@ CONTROL; $wgOut->setRevisionId( $this->mNewRev->getId() ); } - $wgOut->addWikiTextTidy( $this->mNewtext ); + 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" ); + } + } else + $wgOut->addWikiTextTidy( $this->mNewtext ); if( !$this->mNewRev->isCurrent() ) { $wgOut->parserOptions()->setEditSection( $oldEditSectionSetting ); @@ -282,9 +334,8 @@ CONTROL; if ( ! $this->loadNewText() ) { $t = $this->mTitle->getPrefixedText() . " (Diff: {$this->mOldid}, " . "{$this->mNewid})"; - $mtext = wfMsg( 'missingarticle', "<nowiki>$t</nowiki>" ); $wgOut->setPagetitle( wfMsg( 'errorpagetitle' ) ); - $wgOut->addWikitext( $mtext ); + $wgOut->addWikiMsg( 'missingarticle', "<nowiki>$t</nowiki>" ); wfProfileOut( $fname ); return; } @@ -324,10 +375,10 @@ CONTROL; * Returns false if the diff could not be generated, otherwise returns true */ function showDiff( $otitle, $ntitle ) { - global $wgOut, $wgRequest; - $diff = $this->getDiff( $otitle, $ntitle, $wgRequest->getVal( 'action' ) == 'purge' ); + global $wgOut; + $diff = $this->getDiff( $otitle, $ntitle ); if ( $diff === false ) { - $wgOut->addWikitext( wfMsg( 'missingarticle', "<nowiki>(fixme, bug)</nowiki>" ) ); + $wgOut->addWikiMsg( 'missingarticle', "<nowiki>(fixme, bug)</nowiki>" ); return false; } else { $this->showDiffStyle(); @@ -352,11 +403,10 @@ CONTROL; * * @param Title $otitle Old title * @param Title $ntitle New title - * @param bool $skipCache Skip the diff cache for this request? * @return mixed */ - function getDiff( $otitle, $ntitle, $skipCache = false ) { - $body = $this->getDiffBody( $skipCache ); + function getDiff( $otitle, $ntitle ) { + $body = $this->getDiffBody(); if ( $body === false ) { return false; } else { @@ -368,43 +418,49 @@ CONTROL; /** * Get the diff table body, without header * - * @param bool $skipCache Skip cache for this request? * @return mixed */ - function getDiffBody( $skipCache = false ) { + function getDiffBody() { global $wgMemc; $fname = 'DifferenceEngine::getDiffBody'; wfProfileIn( $fname ); // Cacheable? $key = false; - if ( $this->mOldid && $this->mNewid && !$skipCache ) { - // Try cache + if ( $this->mOldid && $this->mNewid ) { $key = wfMemcKey( 'diff', 'version', MW_DIFF_VERSION, 'oldid', $this->mOldid, 'newid', $this->mNewid ); - $difftext = $wgMemc->get( $key ); - if ( $difftext ) { - wfIncrStats( 'diff_cache_hit' ); - $difftext = $this->localiseLineNumbers( $difftext ); - $difftext .= "\n<!-- diff cache key $key -->\n"; - wfProfileOut( $fname ); - return $difftext; - } + // Try cache + if ( !$this->mRefreshCache ) { + $difftext = $wgMemc->get( $key ); + if ( $difftext ) { + wfIncrStats( 'diff_cache_hit' ); + $difftext = $this->localiseLineNumbers( $difftext ); + $difftext .= "\n<!-- diff cache key $key -->\n"; + wfProfileOut( $fname ); + return $difftext; + } + } // don't try to load but save the result } - #loadtext is permission safe, this just clears out the diff + // Loadtext is permission safe, this just clears out the diff if ( !$this->loadText() ) { wfProfileOut( $fname ); return false; } else if ( $this->mOldRev && !$this->mOldRev->userCan(Revision::DELETED_TEXT) ) { - return ''; + return ''; } else if ( $this->mNewRev && !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) { - return ''; + return ''; } $difftext = $this->generateDiffBody( $this->mOldtext, $this->mNewtext ); // Save to cache for 7 days - if ( $key !== false && $difftext !== false ) { + // Only do this for public revs, otherwise an admin can view the diff and a non-admin can nab it! + if ( $this->mOldRev && $this->mOldRev->isDeleted(Revision::DELETED_TEXT) ) { + wfIncrStats( 'diff_uncacheable' ); + } else if ( $this->mNewRev && $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) { + wfIncrStats( 'diff_uncacheable' ); + } else if ( $key !== false && $difftext !== false ) { wfIncrStats( 'diff_cache_miss' ); $wgMemc->set( $key, $difftext, 7*86400 ); } else { @@ -536,15 +592,9 @@ CONTROL; /** * Add the header to a diff body */ - function addHeader( $diff, $otitle, $ntitle, $multi = '' ) { + static function addHeader( $diff, $otitle, $ntitle, $multi = '' ) { global $wgOut; - - if ( $this->mOldRev && $this->mOldRev->isDeleted(Revision::DELETED_TEXT) ) { - $otitle = '<span class="history-deleted">'.$otitle.'</span>'; - } - if ( $this->mNewRev && $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) { - $ntitle = '<span class="history-deleted">'.$ntitle.'</span>'; - } + $header = " <table class='diff'> <col class='diff-marker' /> @@ -615,11 +665,16 @@ CONTROL; } else { $newLink = $this->mNewPage->escapeLocalUrl( 'oldid=' . $this->mNewid ); $newEdit = $this->mNewPage->escapeLocalUrl( 'action=edit&oldid=' . $this->mNewid ); - $this->mPagetitle = htmlspecialchars( wfMsg( 'revisionasof', $timestamp ) ); + $this->mPagetitle = wfMsgHTML( 'revisionasof', $timestamp ); $this->mNewtitle = "<a href='$newLink'>{$this->mPagetitle}</a>" . " (<a href='$newEdit'>" . htmlspecialchars( wfMsg( 'editold' ) ) . "</a>)"; } + if ( !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) { + $this->mNewtitle = "<span class='history-deleted'>{$this->mPagetitle}</span>"; + } else if ( $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) { + $this->mNewtitle = '<span class="history-deleted">'.$this->mNewtitle.'</span>'; + } // Load the old revision object $this->mOldRev = false; @@ -647,12 +702,20 @@ CONTROL; $t = $wgLang->timeanddate( $this->mOldRev->getTimestamp(), true ); $oldLink = $this->mOldPage->escapeLocalUrl( 'oldid=' . $this->mOldid ); $oldEdit = $this->mOldPage->escapeLocalUrl( 'action=edit&oldid=' . $this->mOldid ); - $this->mOldtitle = "<a href='$oldLink'>" . htmlspecialchars( wfMsg( 'revisionasof', $t ) ) - . "</a> (<a href='$oldEdit'>" . htmlspecialchars( wfMsg( 'editold' ) ) . "</a>)"; + $this->mOldPagetitle = htmlspecialchars( wfMsg( 'revisionasof', $t ) ); + $this->mOldtitle = "<a href='$oldLink'>{$this->mOldPagetitle}</a>" + . " (<a href='$oldEdit'>" . htmlspecialchars( wfMsg( 'editold' ) ) . "</a>)"; // Add an "undo" link $newUndo = $this->mNewPage->escapeLocalUrl( 'action=edit&undoafter=' . $this->mOldid . '&undo=' . $this->mNewid); - $this->mNewtitle .= " (<a href='$newUndo'>" . htmlspecialchars( wfMsg( 'editundo' ) ) . "</a>)"; + if ( $this->mNewRev->userCan(Revision::DELETED_TEXT) ) + $this->mNewtitle .= " (<a href='$newUndo'>" . htmlspecialchars( wfMsg( 'editundo' ) ) . "</a>)"; + + if ( !$this->mOldRev->userCan(Revision::DELETED_TEXT) ) { + $this->mOldtitle = "<span class='history-deleted'>{$this->mOldPagetitle}</span>"; + } else if ( $this->mOldRev->isDeleted(Revision::DELETED_TEXT) ) { + $this->mOldtitle = '<span class="history-deleted">'.$this->mOldtitle.'</span>'; + } } return true; @@ -673,7 +736,6 @@ CONTROL; return false; } if ( $this->mOldRev ) { - // FIXME: permission tests $this->mOldtext = $this->mOldRev->revText(); if ( $this->mOldtext === false ) { return false; @@ -1584,7 +1646,7 @@ class DiffFormatter } function _start_block($header) { - echo $header; + echo $header . "\n"; } function _end_block() { @@ -1613,6 +1675,84 @@ class DiffFormatter } } +/** + * A formatter that outputs unified diffs + * @addtogroup DifferenceEngine + */ + +class UnifiedDiffFormatter extends DiffFormatter +{ + var $leading_context_lines = 2; + var $trailing_context_lines = 2; + + function _added($lines) { + $this->_lines($lines, '+'); + } + function _deleted($lines) { + $this->_lines($lines, '-'); + } + function _changed($orig, $closing) { + $this->_deleted($orig); + $this->_added($closing); + } + function _block_header($xbeg, $xlen, $ybeg, $ylen) { + return "@@ -$xbeg,$xlen +$ybeg,$ylen @@"; + } +} + +/** + * A pseudo-formatter that just passes along the Diff::$edits array + * @addtogroup DifferenceEngine + */ +class ArrayDiffFormatter extends DiffFormatter +{ + function format($diff) + { + $oldline = 1; + $newline = 1; + $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( + 'action' => 'delete', + 'old' => $l, + 'oldline' => $oldline++, + ); + } + break; + case 'change': + foreach($edit->orig as $i => $l) + { + $retval[] = array( + 'action' => 'change', + 'old' => $l, + 'new' => @$edit->closing[$i], + 'oldline' => $oldline++, + 'newline' => $newline++, + ); + } + 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 @@ -1828,13 +1968,15 @@ class TableDiffFormatter extends DiffFormatter function _added( $lines ) { foreach ($lines as $line) { echo '<tr>' . $this->emptyLine() . - $this->addedLine( htmlspecialchars ( $line ) ) . "</tr>\n"; + $this->addedLine( '<ins class="diffchange">' . + htmlspecialchars ( $line ) . '</ins>' ) . "</tr>\n"; } } function _deleted($lines) { foreach ($lines as $line) { - echo '<tr>' . $this->deletedLine( htmlspecialchars ( $line ) ) . + echo '<tr>' . $this->deletedLine( '<del class="diffchange">' . + htmlspecialchars ( $line ) . '</del>' ) . $this->emptyLine() . "</tr>\n"; } } |