MediaWiki r26604 - Code Review

Jump to: navigation, search
Repository:MediaWiki
Revision:r26603‎ | r26604 (on ViewVC)‎ | r26605 >
Date:21:07, 11 October 2007
Author:brion
Status:old
Tags:
Comment:
* (bug 7872) Deleted revisions can now be viewed as diffs showing changes
against the previous revision, whether currently deleted or live.
In cases of mixed or merged histories this may not produce ideal results.
Currently only auto-selected previous revision is available to diff against; in future could potentially allow diffing against any other revision.
'Show changes' button may currently display on the individual revision view form even if there's no prior revision available. Should be correct in the list view though.
Modified paths:

Diff [purge]

Index: trunk/phase3/includes/SpecialUndelete.php
===================================================================
--- trunk/phase3/includes/SpecialUndelete.php	(revision 26603)
+++ trunk/phase3/includes/SpecialUndelete.php	(revision 26604)
@@ -194,6 +194,59 @@
 			return null;
 		}
 	}
+	
+	/**
+	 * Return the most-previous revision, either live or deleted, against
+	 * the deleted revision given by timestamp.
+	 *
+	 * May produce unexpected results in case of history merges or other
+	 * unusual time issues.
+	 *
+	 * @param string $timestamp
+	 * @return Revision or null
+	 */
+	function getPreviousRevision( $timestamp ) {
+		$dbr = wfGetDB( DB_SLAVE );
+		
+		// Check the previous deleted revision...
+		$row = $dbr->selectRow( 'archive',
+			'ar_timestamp',
+			array( 'ar_namespace' => $this->title->getNamespace(),
+			       'ar_title' => $this->title->getDbkey(),
+			       'ar_timestamp < ' .
+						$dbr->addQuotes( $dbr->timestamp( $timestamp ) ) ),
+			__METHOD__,
+			array(
+				'ORDER BY' => 'ar_timestamp DESC',
+				'LIMIT' => 1 ) );
+		$prevDeleted = $row ? wfTimestamp( TS_MW, $row->ar_timestamp ) : false;
+		
+		$row = $dbr->selectRow( array( 'page', 'revision' ),
+			array( 'rev_id', 'rev_timestamp' ),
+			array(
+				'page_namespace' => $this->title->getNamespace(),
+				'page_title' => $this->title->getDbkey(),
+				'page_id = rev_page',
+				'rev_timestamp < ' .
+						$dbr->addQuotes( $dbr->timestamp( $timestamp ) ) ),
+			__METHOD__,
+			array(
+				'ORDER BY' => 'rev_timestamp DESC',
+				'LIMIT' => 1 ) );
+		$prevLive = $row ? wfTimestamp( TS_MW, $row->rev_timestamp ) : false;
+		$prevLiveId = $row ? intval( $row->rev_id ) : null;
+		
+		if( $prevLive && $prevLive > $prevDeleted ) {
+			// Most prior revision was live
+			return Revision::newFromId( $prevLiveId );
+		} elseif( $prevDeleted ) {
+			// Most prior revision was deleted
+			return $this->getRevision( $prevDeleted );
+		} else {
+			// No prior revision on this page.
+			return null;
+		}
+	}
 
 	/**
 	 * Get the text from an archive row containing ar_text, ar_flags and ar_text_id
@@ -478,6 +531,7 @@
 			$wgUser->matchEditToken( $request->getVal( 'wpEditToken' ) );
 		$this->mRestore = $request->getCheck( 'restore' ) && $posted;
 		$this->mPreview = $request->getCheck( 'preview' ) && $posted;
+		$this->mDiff = $request->getCheck( 'diff' );
 		$this->mComment = $request->getText( 'wpComment' );
 		
 		if( $par != "" ) {
@@ -619,6 +673,17 @@
 		$user = $skin->userLink( $rev->getUser(), $rev->getUserText() )
 			. $skin->userToolLinks( $rev->getUser(), $rev->getUserText() );
 			
+		
+		if( $this->mDiff ) {
+			$previousRev = $archive->getPreviousRevision( $timestamp );
+			if( $previousRev ) {
+				$this->showDiff( $previousRev, $rev );
+				$wgOut->addHtml( '<hr />' );
+			} else {
+				$wgOut->addHtml( 'No previous revision found.' );
+			}
+		}
+		
 		$wgOut->addHtml( '<p>' . wfMsgHtml( 'undelete-revision', $link, $time, $user ) . '</p>' );
 		
 		wfRunHooks( 'UndeleteShowRevision', array( $this->mTargetObj, $rev ) );
@@ -651,17 +716,84 @@
 				'name' => 'wpEditToken',
 				'value' => $wgUser->editToken() ) ) .
 			wfElement( 'input', array(
-				'type' => 'hidden',
+				'type' => 'submit',
 				'name' => 'preview',
-				'value' => '1' ) ) .
+				'value' => wfMsg( 'showpreview' ) ) ) .
 			wfElement( 'input', array(
+				'name' => 'diff',
 				'type' => 'submit',
-				'value' => wfMsg( 'showpreview' ) ) ) .
+				'value' => wfMsg( 'showdiff' ) ) ) .
 			wfCloseElement( 'form' ) .
 			wfCloseElement( 'div' ) );
 	}
 	
 	/**
+	 * Build a diff display between this and the previous either deleted
+	 * or non-deleted edit.
+	 * @param Revision $previousRev
+	 * @param Revision $currentRev
+	 * @return string HTML
+	 */
+	function showDiff( $previousRev, $currentRev ) {
+		global $wgOut, $wgUser;
+		
+		$diffEngine = new DifferenceEngine();
+		$diffEngine->showDiffStyle();
+		$wgOut->addHtml(
+			"<div>" .
+			"<table border='0' width='98%' cellpadding='0' cellspacing='4' class='diff'>" .
+			"<col class='diff-marker' />" .
+			"<col class='diff-content' />" .
+			"<col class='diff-marker' />" .
+			"<col class='diff-content' />" .
+			"<tr>" .
+				"<td colspan='2' width='50%' align='center' class='diff-otitle'>" .
+				$this->diffHeader( $previousRev ) .
+				"</td>" .
+				"<td colspan='2' width='50%' align='center' class='diff-ntitle'>" .
+				$this->diffHeader( $currentRev ) .
+				"</td>" .
+			"</tr>" .
+			$diffEngine->generateDiffBody(
+				$previousRev->getText(), $currentRev->getText() ) .
+			"</table>" .
+			"</div>\n" );
+
+	}
+	
+	private function diffHeader( $rev ) {
+		global $wgUser, $wgLang, $wgLang;
+		$sk = $wgUser->getSkin();
+		$isDeleted = !( $rev->getId() && $rev->getTitle() );
+		if( $isDeleted ) {
+			/// @fixme $rev->getTitle() is null for deleted revs...?
+			$targetPage = SpecialPage::getTitleFor( 'Undelete' );
+			$targetQuery = 'target=' .
+				$this->mTargetObj->getPrefixedUrl() .
+				'&timestamp=' .
+				wfTimestamp( TS_MW, $rev->getTimestamp() );
+		} else {
+			/// @fixme getId() may return non-zero for deleted revs...
+			$targetPage = $rev->getTitle();
+			$targetQuery = 'oldid=' . $rev->getId();
+		}
+		return
+			'<div id="mw-diff-otitle1"><strong>' .
+				$sk->makeLinkObj( $targetPage,
+					wfMsgHtml( 'revisionasof',
+						$wgLang->timeanddate( $rev->getTimestamp() ) ),
+					$targetQuery ) .
+				( $isDeleted ? ' ' . wfMsgHtml( 'deletedrev' ) : '' ) .
+			'</strong></div>' .
+			'<div id="mw-diff-otitle2">' .
+				$sk->revUserTools( $rev ) . '<br/>' .
+			'</div>' .
+			'<div id="mw-diff-otitle3">' .
+				$sk->revComment( $rev ) . '<br/>' .
+			'</div>';
+	}
+	
+	/**
 	 * Show a deleted file version requested by the visitor.
 	 */
 	function showFile( $key ) {
@@ -792,16 +924,32 @@
 			# The page's stored (deleted) history:
 			$wgOut->addHTML("<ul>");
 			$target = urlencode( $this->mTarget );
+			$remaining = $revisions->numRows();
+			$earliestLiveTime = $this->getEarliestTime( $this->mTargetObj );
+			
 			while( $row = $revisions->fetchObject() ) {
+				$remaining--;
 				$ts = wfTimestamp( TS_MW, $row->ar_timestamp );
 				if ( $this->mAllowed ) {
 					$checkBox = Xml::check( "ts$ts" );
 					$pageLink = $sk->makeKnownLinkObj( $titleObj,
 						$wgLang->timeanddate( $ts, true ),
 						"target=$target&timestamp=$ts" );
+					if( ($remaining > 0) ||
+							($earliestLiveTime && $ts > $earliestLiveTime ) ) {
+						$diffLink = '(' .
+							$sk->makeKnownLinkObj( $titleObj,
+								wfMsgHtml( 'diff' ),
+								"target=$target&timestamp=$ts&diff=prev" ) .
+							')';
+					} else {
+						// No older revision to diff against
+						$diffLink = '';
+					}
 				} else {
 					$checkBox = '';
 					$pageLink = $wgLang->timeanddate( $ts, true );
+					$diffLink = '';
 				}
 				$userLink = $sk->userLink( $row->ar_user, $row->ar_user_text ) . $sk->userToolLinks( $row->ar_user, $row->ar_user_text );
 				$stxt = '';
@@ -813,7 +961,7 @@
 					}
 				}
 				$comment = $sk->commentBlock( $row->ar_comment );
-				$wgOut->addHTML( "<li>$checkBox $pageLink . . $userLink $stxt $comment</li>\n" );
+				$wgOut->addHTML( "<li>$checkBox $pageLink $diffLink . . $userLink $stxt $comment</li>\n" );
 
 			}
 			$revisions->free();
@@ -863,6 +1011,18 @@
 
 		return true;
 	}
+	
+	private function getEarliestTime( $title ) {
+		$dbr = wfGetDB( DB_SLAVE );
+		if( $title->exists() ) {
+			$min = $dbr->selectField( 'revision',
+				'MIN(rev_timestamp)',
+				array( 'rev_page' => $title->getArticleId() ),
+				__METHOD__ );
+			return wfTimestampOrNull( TS_MW, $min );
+		}
+		return null;
+	}
 
 	function undelete() {
 		global $wgOut, $wgUser;
Index: trunk/phase3/RELEASE-NOTES
===================================================================
--- trunk/phase3/RELEASE-NOTES	(revision 26603)
+++ trunk/phase3/RELEASE-NOTES	(revision 26604)
@@ -35,6 +35,8 @@
 * Clarify instructions given when an exception is thrown
 * AuthPlugin added strictUserAuth() method to allow per-user override
   of the strict() authentication behavior.
+* (bug 7872) Deleted revisions can now be viewed as diffs showing changes
+  against the previous revision, whether currently deleted or live.
 
 
 === Bug fixes in 1.12 ===

Status & tagging log

  • 15:21, 12 September 2011 Meno25 (Talk | contribs) changed the status of r26604 [removed: ok added: old]
Personal tools
Namespaces
Variants
Views
Actions
Site
Support
Download
Development
Communication
Toolbox