X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2FDifferenceEngine.php;h=349c88ec58923a79cfba4f928bf139e0ff03fee5;hb=839f3ffd651465380923a5110dc834c23fd9c27f;hp=af65ce3aaf31bfffa566b8772b6f476277c7abaf;hpb=113bb1c772d2ddb70345e5027676338ad00f1c2a;p=lhc%2Fweb%2Fwiklou.git
diff --git a/includes/DifferenceEngine.php b/includes/DifferenceEngine.php
index af65ce3aaf..349c88ec58 100644
--- a/includes/DifferenceEngine.php
+++ b/includes/DifferenceEngine.php
@@ -5,6 +5,14 @@
* @addtogroup DifferenceEngine
*/
+/**
+ * Constant to indicate diff cache compatibility.
+ * Bump this when changing the diff formatting in a way that
+ * fixes important bugs or such to force cached diff views to
+ * clear.
+ */
+define( 'MW_DIFF_VERSION', '1.11a' );
+
/**
* @todo document
* @public
@@ -30,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");
@@ -60,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 ) {
@@ -148,8 +158,43 @@ CONTROL;
} else {
$rollback = '';
}
- if( $wgUseRCPatrol && $this->mRcidMarkPatrolled != 0 && $wgUser->isAllowed( 'patrol' ) ) {
- $patrol = ' [' . $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'markaspatrolleddiff' ), "action=markpatrolled&rcid={$this->mRcidMarkPatrolled}" ) . ']';
+
+ // Prepare a change patrol link, if applicable
+ if( $wgUseRCPatrol && $wgUser->isAllowed( 'patrol' ) ) {
+ // If we've been given an explicit change identifier, use it; saves time
+ if( $this->mRcidMarkPatrolled ) {
+ $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' => $db->timestamp( $this->mNewRev->getTimestamp() ),
+ 'rc_this_oldid' => $this->mNewid,
+ 'rc_last_oldid' => $this->mOldid,
+ 'rc_patrolled' => 0,
+ ),
+ __METHOD__
+ );
+ if( $change instanceof RecentChange ) {
+ $rcid = $change->mAttribs['rc_id'];
+ } else {
+ // None found
+ $rcid = 0;
+ }
+ }
+ // Build the link
+ if( $rcid ) {
+ $patrol = ' [' . $sk->makeKnownLinkObj(
+ $this->mTitle,
+ wfMsgHtml( 'markaspatrolleddiff' ),
+ "action=markpatrolled&rcid={$rcid}"
+ ) . ']';
+ } else {
+ $patrol = '';
+ }
} else {
$patrol = '';
}
@@ -175,15 +220,50 @@ 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 = "$ldel";
+ }
+ $ldel = " ($ldel) ";
+ // 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 = "$rdel";
+ }
+ $rdel = " ($rdel) ";
+ }
- $oldHeader = "{$this->mOldtitle}
" .
- $sk->revUserTools( $this->mOldRev ) . "
" .
- $oldminor . $sk->revComment( $this->mOldRev, !$diffOnly ) . "
" .
- $prevlink;
- $newHeader = "{$this->mNewtitle}
" .
- $sk->revUserTools( $this->mNewRev ) . " $rollback
" .
- $newminor . $sk->revComment( $this->mNewRev, !$diffOnly ) . "
" .
- $nextlink . $patrol;
+ $oldHeader = '
and don't parse + $m = array(); + preg_match( '!\.(css|js)$!u', $this->mTitle->getText(), $m ); + $wgOut->addHtml( "\n" ); + $wgOut->addHtml( htmlspecialchars( $this->mNewtext ) ); + $wgOut->addHtml( "\n\n" ); + } + } else + $wgOut->addWikiTextTidy( $this->mNewtext ); if( !$this->mNewRev->isCurrent() ) { $wgOut->parserOptions()->setEditSection( $oldEditSectionSetting ); @@ -288,15 +383,29 @@ CONTROL; $wgOut->addWikitext( wfMsg( 'missingarticle', "(fixme, bug) " ) ); return false; } else { + $this->showDiffStyle(); $wgOut->addHTML( $diff ); return true; } } + + /** + * Add style sheets and supporting JS for diff display. + */ + function showDiffStyle() { + global $wgStylePath, $wgStyleVersion, $wgOut; + $wgOut->addStyle( 'common/diff.css' ); + + // JS is needed to detect old versions of Mozilla to work around an annoyance bug. + $wgOut->addScript( "" ); + } /** - * Get diff table, including header - * Note that the interface has changed, it's no longer static. - * Returns false on error + * Get complete diff table, including header + * + * @param Title $otitle Old title + * @param Title $ntitle New title + * @return mixed */ function getDiff( $otitle, $ntitle ) { $body = $this->getDiffBody(); @@ -310,8 +419,8 @@ CONTROL; /** * Get the diff table body, without header - * Results are cached - * Returns false on error + * + * @return mixed */ function getDiffBody() { global $wgMemc; @@ -321,32 +430,39 @@ CONTROL; // Cacheable? $key = false; if ( $this->mOldid && $this->mNewid ) { + $key = wfMemcKey( 'diff', 'version', MW_DIFF_VERSION, 'oldid', $this->mOldid, 'newid', $this->mNewid ); // Try cache - $key = wfMemcKey( 'diff', 'oldid', $this->mOldid, 'newid', $this->mNewid ); - $difftext = $wgMemc->get( $key ); - if ( $difftext ) { - wfIncrStats( 'diff_cache_hit' ); - $difftext = $this->localiseLineNumbers( $difftext ); - $difftext .= "\n\n"; - wfProfileOut( $fname ); - return $difftext; - } + if ( !$this->mRefreshCache ) { + $difftext = $wgMemc->get( $key ); + if ( $difftext ) { + wfIncrStats( 'diff_cache_hit' ); + $difftext = $this->localiseLineNumbers( $difftext ); + $difftext .= "\n\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 { @@ -478,20 +594,18 @@ 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 = ''.$otitle.''; - } - if ( $this->mNewRev && $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) { - $ntitle = ''.$ntitle.''; - } + $header = " -
{$otitle} | -{$ntitle} | +{$otitle} | +{$ntitle} | ||||
\n" . - ' | |||||||
\n" . + ' | + | {$line} | "; + return $this->wrapLine( '+', 'diff-addedline', $line ); } # HTML-escape parameter before calling this function deletedLine( $line ) { - return "- | {$line} | "; + return $this->wrapLine( '-', 'diff-deletedline', $line ); } # HTML-escape parameter before calling this function contextLine( $line ) { - return "{$line} | "; + return $this->wrapLine( ' ', 'diff-context', $line ); + } + + private function wrapLine( $marker, $class, $line ) { + if( $line !== '' ) { + // The$marker | $line | "; } function emptyLine() { @@ -1758,13 +1970,15 @@ class TableDiffFormatter extends DiffFormatter function _added( $lines ) { foreach ($lines as $line) { echo '