From: Marius Hoch Date: Thu, 1 Nov 2012 20:04:12 +0000 (+0100) Subject: (bug 39397) Only show rollback links if they work X-Git-Tag: 1.31.0-rc.0~21093 X-Git-Url: http://git.cyclocoop.org/url?a=commitdiff_plain;h=a53fe6f080a2dfe48ed77c09af9e09ef37085408;p=lhc%2Fweb%2Fwiklou.git (bug 39397) Only show rollback links if they work To only show rollback links if they work I had to patch Linker to have a function (Linker::rollbackData) which can verify that the editor isn't the only editor of the page. Furthermore it is checked that the user name or the text of the revision we might rollback to isn't deleted. Due to the fact that I've altered the already existing method which showed how many edits a rollback will revert for that, this wont affect the performance. Change-Id: I5d1adec993370c39ae8c5c712edd919d456441c6 --- diff --git a/RELEASE-NOTES-1.21 b/RELEASE-NOTES-1.21 index 7d0ad48948..de545da7a5 100644 --- a/RELEASE-NOTES-1.21 +++ b/RELEASE-NOTES-1.21 @@ -75,6 +75,7 @@ production. dropExtensionIndex and renameExtensionIndex. * New preference type - 'api'. Preferences of this type are not shown on Special:Preferences, but are still available via the action=options API. +* (bug 39397) Hide rollback link if a user is the only contributor of the page. === Bug fixes in 1.21 === * (bug 40353) SpecialDoubleRedirect should support interwiki redirects. diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index c529ef7d87..f8738ddbfe 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -2832,7 +2832,8 @@ $wgSend404Code = true; /** * The $wgShowRollbackEditCount variable is used to show how many edits will be * rollback. The numeric value of the varible are the limit up to are counted. - * If the value is false or 0, the edits are not counted. + * If the value is false or 0, the edits are not counted. Disabling this will + * furthermore prevent MediaWiki from hiding some useless rollback links. * * @since 1.20 */ diff --git a/includes/Linker.php b/includes/Linker.php index 6b0d4442ef..5c41b42fbe 100644 --- a/includes/Linker.php +++ b/includes/Linker.php @@ -1756,19 +1756,101 @@ class Linker { * changes, so this allows sysops to combat a busy vandal without bothering * other users. * + * If the option verify is set this function will return the link only in case the + * revision can be reverted. Please note that due to performance limitations + * it might be assumed that a user isn't the only contributor of a page while + * (s)he is, which will lead to useless rollback links. Furthermore this wont + * work if $wgShowRollbackEditCount is disabled, so this can only function + * as an additional check. + * + * If the option noBrackets is set the rollback link wont be enclosed in [] + * * @param $rev Revision object * @param $context IContextSource context to use or null for the main context. + * @param $options array * @return string */ - public static function generateRollback( $rev, IContextSource $context = null ) { + public static function generateRollback( $rev, IContextSource $context = null, $options = array( 'verify' ) ) { if ( $context === null ) { $context = RequestContext::getMain(); } + $editCount = false; + if ( in_array( 'verify', $options ) ) { + $editCount = self::getRollbackEditCount( $rev, true ); + if ( $editCount === false ) { + return ''; + } + } - return '' - . $context->msg( 'brackets' )->rawParams( - self::buildRollbackLink( $rev, $context ) )->plain() - . ''; + $inner = self::buildRollbackLink( $rev, $context, $editCount ); + + if ( !in_array( 'noBrackets', $options ) ) { + $inner = $context->msg( 'brackets' )->rawParams( $inner )->plain(); + } + + return '' . $inner . ''; + } + + /** + * This function will return the number of revisions which a rollback + * would revert and, if $verify is set it will verify that a revision + * can be reverted (that the user isn't the only contributor and the + * revision we might rollback to isn't deleted). These checks can only + * function as an additional check as this function only checks against + * the last $wgShowRollbackEditCount edits. + * + * Returns null if $wgShowRollbackEditCount is disabled or false if $verify + * is set and the user is the only contributor of the page. + * + * @param $rev Revision object + * @param $verify Bool Try to verfiy that this revision can really be rolled back + * @return integer|bool|null + */ + public static function getRollbackEditCount( $rev, $verify ) { + global $wgShowRollbackEditCount; + if ( !is_int( $wgShowRollbackEditCount ) || !$wgShowRollbackEditCount > 0 ) { + // Nothing has happened, indicate this by returning 'null' + return null; + } + + $dbr = wfGetDB( DB_SLAVE ); + + // Up to the value of $wgShowRollbackEditCount revisions are counted + $res = $dbr->select( + 'revision', + array( 'rev_user_text', 'rev_deleted' ), + // $rev->getPage() returns null sometimes + array( 'rev_page' => $rev->getTitle()->getArticleID() ), + __METHOD__, + array( + 'USE INDEX' => array( 'revision' => 'page_timestamp' ), + 'ORDER BY' => 'rev_timestamp DESC', + 'LIMIT' => $wgShowRollbackEditCount + 1 + ) + ); + + $editCount = 0; + $moreRevs = false; + foreach ( $res as $row ) { + if ( $rev->getRawUserText() != $row->rev_user_text ) { + if ( $verify && ( $row->rev_deleted & Revision::DELETED_TEXT || $row->rev_deleted & Revision::DELETED_USER ) ) { + // If the user or the text of the revision we might rollback to is deleted in some way we can't rollback + // Similar to the sanity checks in WikiPage::commitRollback + return false; + } + $moreRevs = true; + break; + } + $editCount++; + } + + if ( $verify && $editCount <= $wgShowRollbackEditCount && !$moreRevs ) { + // We didn't find at least $wgShowRollbackEditCount revisions made by the current user + // and there weren't any other revisions. That means that the current user is the only + // editor, so we can't rollback + return false; + } + return $editCount; } /** @@ -1776,9 +1858,10 @@ class Linker { * * @param $rev Revision object * @param $context IContextSource context to use or null for the main context. + * @param $editCount integer Number of edits that would be reverted * @return String: HTML fragment */ - public static function buildRollbackLink( $rev, IContextSource $context = null ) { + public static function buildRollbackLink( $rev, IContextSource $context = null, $editCount = false ) { global $wgShowRollbackEditCount, $wgMiserMode; // To config which pages are effected by miser mode @@ -1810,25 +1893,8 @@ class Linker { } if( !$disableRollbackEditCount && is_int( $wgShowRollbackEditCount ) && $wgShowRollbackEditCount > 0 ) { - $dbr = wfGetDB( DB_SLAVE ); - - // Up to the value of $wgShowRollbackEditCount revisions are counted - $res = $dbr->select( 'revision', - array( 'rev_id', 'rev_user_text' ), - // $rev->getPage() returns null sometimes - array( 'rev_page' => $rev->getTitle()->getArticleID() ), - __METHOD__, - array( 'USE INDEX' => 'page_timestamp', - 'ORDER BY' => 'rev_timestamp DESC', - 'LIMIT' => $wgShowRollbackEditCount + 1 ) - ); - - $editCount = 0; - while( $row = $dbr->fetchObject( $res ) ) { - if( $rev->getUserText() != $row->rev_user_text ) { - break; - } - $editCount++; + if ( !is_numeric( $editCount ) ) { + $editCount = self::getRollbackEditCount( $rev, false ); } if( $editCount > $wgShowRollbackEditCount ) { diff --git a/includes/actions/HistoryAction.php b/includes/actions/HistoryAction.php index c33423d304..43a03db2b7 100644 --- a/includes/actions/HistoryAction.php +++ b/includes/actions/HistoryAction.php @@ -626,9 +626,12 @@ class HistoryPager extends ReverseChronologicalPager { # Rollback and undo links if ( $prevRev && $this->getTitle()->quickUserCan( 'edit', $user ) ) { if ( $latest && $this->getTitle()->quickUserCan( 'rollback', $user ) ) { - $this->preventClickjacking(); - $tools[] = '' . - Linker::buildRollbackLink( $rev, $this->getContext() ) . ''; + // Get a rollback link without the brackets + $rollbackLink = Linker::generateRollback( $rev, $this->getContext(), array( 'verify', 'noBrackets' ) ); + if ( $rollbackLink ) { + $this->preventClickjacking(); + $tools[] = $rollbackLink; + } } if ( !$rev->isDeleted( Revision::DELETED_TEXT ) diff --git a/includes/diff/DifferenceEngine.php b/includes/diff/DifferenceEngine.php index 6fcf0e8eac..97553e682c 100644 --- a/includes/diff/DifferenceEngine.php +++ b/includes/diff/DifferenceEngine.php @@ -294,8 +294,11 @@ class DifferenceEngine extends ContextSource { if ( $samePage && $this->mNewPage->quickUserCan( 'edit', $user ) ) { if ( $this->mNewRev->isCurrent() && $this->mNewPage->userCan( 'rollback', $user ) ) { - $out->preventClickjacking(); - $rollback = '   ' . Linker::generateRollback( $this->mNewRev, $this->getContext() ); + $rollbackLink = Linker::generateRollback( $this->mNewRev, $this->getContext() ); + if ( $rollbackLink ) { + $out->preventClickjacking(); + $rollback = '   ' . $rollbackLink; + } } if ( !$this->mOldRev->isDeleted( Revision::DELETED_TEXT ) && !$this->mNewRev->isDeleted( Revision::DELETED_TEXT ) ) { $undoLink = ' ' . $this->msg( 'parentheses' )->rawParams(