From: Aaron Schulz Date: Wed, 14 Mar 2007 15:50:06 +0000 (+0000) Subject: *Merge in phase3_rev_deleted/includes X-Git-Tag: 1.31.0-rc.0~53742 X-Git-Url: https://git.cyclocoop.org/%242?a=commitdiff_plain;h=2448539ad9274c75b9972884dc164dffd50497b5;p=lhc%2Fweb%2Fwiklou.git *Merge in phase3_rev_deleted/includes --- diff --git a/includes/Article.php b/includes/Article.php index 3c8d10e094..e5a04e86e1 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -1782,6 +1782,8 @@ class Article { $confirm = $wgRequest->wasPosted() && $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) ); $reason = $wgRequest->getText( 'wpReason' ); + # Flag to hide all contents of the archived revisions + $suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgUser->isAllowed('deleterevision'); # This code desperately needs to be totally rewritten @@ -1813,7 +1815,7 @@ class Article { } if( $confirm ) { - $this->doDelete( $reason ); + $this->doDelete( $reason, $suppress ); if( $wgRequest->getCheck( 'wpWatch' ) ) { $this->doWatch(); } elseif( $this->mTitle->userIsWatching() ) { @@ -1959,7 +1961,14 @@ class Article { $delcom = htmlspecialchars( wfMsg( 'deletecomment' ) ); $token = htmlspecialchars( $wgUser->editToken() ); $watch = Xml::checkLabel( wfMsg( 'watchthis' ), 'wpWatch', 'wpWatch', $wgUser->getBoolOption( 'watchdeletion' ) || $this->mTitle->userIsWatching(), array( 'tabindex' => '2' ) ); - + if ( $wgUser->isAllowed( 'deleterevision' ) ) { + $supress = " "; + $supress .= Xml::checkLabel( wfMsg( 'revdelete-suppress' ), 'wpSuppress', 'wpSuppress', false, array( 'tabindex' => '2' ) ); + $supress .= ""; + } else { + $supress = ''; + } + $wgOut->addHTML( "
@@ -1971,6 +1980,7 @@ class Article { + $supress @@ -2009,12 +2019,12 @@ class Article { /** * Perform a deletion and output success or failure messages */ - function doDelete( $reason ) { + function doDelete( $reason, $suppress = false ) { global $wgOut, $wgUser; wfDebug( __METHOD__."\n" ); if (wfRunHooks('ArticleDelete', array(&$this, &$wgUser, &$reason))) { - if ( $this->doDeleteArticle( $reason ) ) { + if ( $this->doDeleteArticle( $reason, $suppress ) ) { $deleted = wfEscapeWikiText( $this->mTitle->getPrefixedText() ); $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) ); @@ -2037,7 +2047,7 @@ class Article { * Deletes the article with database consistency, writes logs, purges caches * Returns success */ - function doDeleteArticle( $reason ) { + function doDeleteArticle( $reason, $suppress = false ) { global $wgUseSquid, $wgDeferredUpdateList; global $wgUseTrackbacks; @@ -2055,6 +2065,17 @@ class Article { $u = new SiteStatsUpdate( 0, 1, -(int)$this->isCountable( $this->getContent() ), -1 ); array_push( $wgDeferredUpdateList, $u ); + // Bitfields to further supress the content + if ( $suppress ) { + $bitfield = 0; + $bitfield |= Revision::DELETED_TEXT; + $bitfield |= Revision::DELETED_COMMENT; + $bitfield |= Revision::DELETED_USER; + $bitfield |= Revision::DELETED_RESTRICTED; + } else { + $bitfield = 'rev_deleted'; + } + // For now, shunt the revision data into the archive table. // Text is *not* removed from the text table; bulk storage // is left intact to avoid breaking block-compression or @@ -2078,7 +2099,7 @@ class Article { 'ar_text_id' => 'rev_text_id', 'ar_text' => '\'\'', // Be explicit to appease 'ar_flags' => '\'\'', // MySQL's "strict mode"... - 'ar_len' => 'rev_len' + 'ar_deleted' => $bitfield ), array( 'page_id' => $id, 'page_id = rev_page' @@ -2119,8 +2140,9 @@ class Article { # Clear caches Article::onArticleDelete( $this->mTitle ); - # Log the deletion - $log = new LogPage( 'delete' ); + # Log the deletion, if the page was suppressed, log it at Oversight instead + $logtype = ($suppress) ? 'oversight' : 'delete'; + $log = new LogPage( $logtype ); $log->addEntry( 'delete', $this->mTitle, $reason ); # Clear the cached article id so the interface doesn't act like we exist @@ -2226,8 +2248,13 @@ class Article { ); } - # Get the edit summary $target = Revision::newFromId( $s->rev_id ); + # Revision *must* be public and we don't well handle deleted edits on top + if ( $target->isDeleted(REVISION::DELETED_TEXT) ) { + $wgOut->setPageTitle( wfMsg('rollbackfailed') ); + $wgOut->addHTML( wfMsg( 'missingarticle' ) ); + } + # Get the edit summary $newComment = wfMsgForContent( 'revertpage', $target->getUserText(), $from ); $newComment = $wgRequest->getText( 'summary', $newComment ); @@ -2405,10 +2432,30 @@ class Article { ? wfMsg( 'diff' ) : $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=next&oldid='.$oldid ); - $userlinks = $sk->userLink( $revision->getUser(), $revision->getUserText() ) - . $sk->userToolLinks( $revision->getUser(), $revision->getUserText() ); + $cdel=''; + if( $wgUser->isAllowed( 'deleterevision' ) ) { + $revdel = SpecialPage::getTitleFor( 'Revisiondelete' ); + if( $revision->isCurrent() ) { + // We don't handle top deleted edits too well + $cdel = wfMsgHtml('rev-delundel'); + } else if( !$revision->userCan( Revision::DELETED_RESTRICTED ) ) { + // If revision was hidden from sysops + $cdel = wfMsgHtml('rev-delundel'); + } else { + $cdel = $sk->makeKnownLinkObj( $revdel, + wfMsgHtml('rev-delundel'), + 'target=' . urlencode( $this->mTitle->getPrefixedDbkey() ) . + '&oldid=' . urlencode( $oldid ) ); + // Bolden oversighted content + if( $revision->isDeleted( Revision::DELETED_RESTRICTED ) ) + $cdel = "$cdel"; + } + $cdel = "($cdel)"; + } + + $userlinks = $sk->revUserTools( $revision, true ); - $r = "\n\t\t\t\t
" . wfMsg( 'revision-info', $td, $userlinks ) . "
\n" . + $r = "\n\t\t\t\t
" . "$cdel" . wfMsg( 'revision-info', $td, $userlinks ) . "
\n" . "\n\t\t\t\t
" . wfMsg( 'revision-nav', $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "
\n\t\t\t"; $wgOut->setSubtitle( $r ); } diff --git a/includes/ChangesList.php b/includes/ChangesList.php index 43fd543703..d909d63fca 100644 --- a/includes/ChangesList.php +++ b/includes/ChangesList.php @@ -1,5 +1,6 @@ mAttribs = $rc->mAttribs; $rc2->mExtra = $rc->mExtra; @@ -24,13 +27,14 @@ class RCCacheEntry extends RecentChange } ; /** + * @package MediaWiki */ class ChangesList { # Called by history lists and recent changes # /** @todo document */ - function __construct( &$skin ) { + function ChangesList( &$skin ) { $this->skin =& $skin; $this->preCacheMessages(); } @@ -43,7 +47,7 @@ class ChangesList { * @return ChangesList derivative */ public static function newFromUser( &$user ) { - $sk = $user->getSkin(); + $sk =& $user->getSkin(); $list = NULL; if( wfRunHooks( 'FetchChangesList', array( &$user, &$sk, &$list ) ) ) { return $user->getOption( 'usenewrc' ) ? new EnhancedChangesList( $sk ) : new OldChangesList( $sk ); @@ -77,7 +81,7 @@ class ChangesList { : $nothing; $f .= $bot ? '' . $this->message['boteditletter'] . '' : $nothing; $f .= $patrolled ? '!' : $nothing; - return $f; + return "$f"; } /** @@ -103,6 +107,32 @@ class ChangesList { } } + /** + * int $field one of DELETED_* bitfield constants + * @return bool + */ + function isDeleted( $rc, $field ) { + return ($rc->mAttribs['rc_deleted'] & $field) == $field; + } + + /** + * Determine if the current user is allowed to view a particular + * field of this revision, if it's marked as deleted. + * @param int $field + * @return bool + */ + function userCan( $rc, $field ) { + if( ( $rc->mAttribs['rc_deleted'] & $field ) == $field ) { + global $wgUser; + $permission = ( $rc->mAttribs['rc_deleted'] & Revision::DELETED_RESTRICTED ) == Revision::DELETED_RESTRICTED + ? 'hiderevision' + : 'deleterevision'; + wfDebug( "Checking for $permission due to $field match on $rc->mAttribs['rc_deleted']\n" ); + return $wgUser->isAllowed( $permission ); + } else { + return true; + } + } function insertMove( &$s, $rc ) { # Diff @@ -138,10 +168,11 @@ class ChangesList { $s .= '(' . $this->skin->makeKnownLinkObj($title, $logname ) . ')'; } - function insertDiffHist(&$s, &$rc, $unpatrolled) { # Diff link - if( $rc->mAttribs['rc_type'] == RC_NEW || $rc->mAttribs['rc_type'] == RC_LOG ) { + if( !$this->userCan($rc,Revision::DELETED_TEXT) ) { + $diffLink = $this->message['diff']; + } else if( $rc->mAttribs['rc_type'] == RC_NEW || $rc->mAttribs['rc_type'] == RC_LOG) { $diffLink = $this->message['diff']; } else { $rcidparam = $unpatrolled @@ -172,7 +203,12 @@ class ChangesList { $params = ( $unpatrolled && $rc->mAttribs['rc_type'] == RC_NEW ) ? 'rcid='.$rc->mAttribs['rc_id'] : ''; - $articlelink = ' '. $this->skin->makeKnownLinkObj( $rc->getTitle(), '', $params ); + if( $this->isDeleted($rc,Revision::DELETED_TEXT) ) { + $articlelink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '', $params ); + $articlelink = ''.$articlelink.''; + } else { + $articlelink = ' '. $this->skin->makeKnownLinkObj( $rc->getTitle(), '', $params ); + } if($watched) $articlelink = ''.$articlelink.''; global $wgContLang; $articlelink .= $wgContLang->getDirMark(); @@ -188,15 +224,37 @@ class ChangesList { /** Insert links to user page, user talk page and eventually a blocking link */ function insertUserRelatedLinks(&$s, &$rc) { - $s .= $this->skin->userLink( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] ); - $s .= $this->skin->userToolLinks( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] ); + if ( $this->isDeleted($rc,Revision::DELETED_USER) ) { + $s .= ' ' . wfMsgHtml('rev-deleted-user') . ''; + } else { + $s .= $this->skin->userLink( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] ); + $s .= $this->skin->userToolLinks( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] ); + } + } + + /** insert a formatted action */ + function insertAction(&$s, &$rc) { + # Add comment + if( $rc->mAttribs['rc_type'] == RC_LOG ) { + // log action + if ( $this->isDeleted($rc,LogViewer::DELETED_ACTION) ) { + $s .= ' ' . wfMsgHtml('rev-deleted-event') . ''; + } else { + $s .= ' ' . LogPage::actionText( $rc->mAttribs['rc_log_type'], $rc->mAttribs['rc_log_action'], $rc->getTitle(), $this->skin, LogPage::extractParams($rc->mAttribs['rc_params']), true, true ); + } + } } /** insert a formatted comment */ function insertComment(&$s, &$rc) { # Add comment if( $rc->mAttribs['rc_type'] != RC_MOVE && $rc->mAttribs['rc_type'] != RC_MOVE_OVER_REDIRECT ) { - $s .= $this->skin->commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() ); + // log comment + if ( $this->isDeleted($rc,Revision::DELETED_COMMENT) ) { + $s .= ' ' . wfMsgHtml('rev-deleted-comment') . ''; + } else { + $s .= $this->skin->commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() ); + } } } @@ -242,7 +300,6 @@ class OldChangesList extends ChangesList { wfProfileIn( $fname ); # Extract DB fields into local scope - // FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables. extract( $rc->mAttribs ); # Should patrol-related stuff be shown? @@ -252,19 +309,23 @@ class OldChangesList extends ChangesList { $s .= '
  • '; - // moved pages + // Moved pages if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) { $this->insertMove( $s, $rc ); - // log entries - } elseif ( $rc_namespace == NS_SPECIAL ) { + // Log entries (old format) or log targets, and special pages + } elseif( $rc_namespace == NS_SPECIAL ) { list( $specialName, $specialSubpage ) = SpecialPage::resolveAliasWithSubpage( $rc_title ); if ( $specialName == 'Log' ) { $this->insertLog( $s, $rc->getTitle(), $specialSubpage ); } else { wfDebug( "Unexpected special page in recentchanges\n" ); } - // all other stuff - } else { + // Log entries + } elseif( $rc_log_type !='' ) { + $logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL ); + $this->insertLog( $s, $logtitle, $rc_log_type ); + // All other stuff + } else { wfProfileIn($fname.'-page'); $this->insertDiffHist($s, $rc, $unpatrolled); @@ -285,9 +346,15 @@ class OldChangesList extends ChangesList { } $this->insertUserRelatedLinks($s,$rc); + $this->insertAction($s, $rc); $this->insertComment($s, $rc); - - $s .= rtrim(' ' . $this->numberofWatchingusers($rc->numberofWatchingusers)); + + # Mark revision as deleted + if ( $this->isDeleted($rc,Revision::DELETED_TEXT) ) + $s .= ' ' . wfMsgHtml( 'deletedrev' ) . ''; + if($rc->numberofWatchingusers > 0) { + $s .= ' ' . wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($rc->numberofWatchingusers)); + } $s .= "
  • \n"; @@ -313,7 +380,6 @@ class EnhancedChangesList extends ChangesList { $rc = RCCacheEntry::newFromParent( $baseRC ); # Extract fields from DB into the function scope (rc_xxxx variables) - // FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables. extract( $rc->mAttribs ); $curIdEq = 'curid=' . $rc_cur_id; @@ -335,12 +401,14 @@ class EnhancedChangesList extends ChangesList { $rc->unpatrolled = false; } + $showrev=true; # Make article link if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) { $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir"; $clink = wfMsg( $msg, $this->skin->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ), $this->skin->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) ); - } elseif( $rc_namespace == NS_SPECIAL ) { + } else if( $rc_namespace == NS_SPECIAL ) { + // Log entries (old format) and special pages list( $specialName, $logtype ) = SpecialPage::resolveAliasWithSubpage( $rc_title ); if ( $specialName == 'Log' ) { # Log updates, etc @@ -350,7 +418,16 @@ class EnhancedChangesList extends ChangesList { wfDebug( "Unexpected special page in recentchanges\n" ); $clink = ''; } - } elseif( $rc->unpatrolled && $rc_type == RC_NEW ) { + } elseif ( $rc_log_type !='' ) { + // Log entries + $logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL ); + $logname = LogPage::logName( $rc_log_type ); + $clink = '(' . $this->skin->makeKnownLinkObj($logtitle, $logname ) . ')'; + } if ( $this->isDeleted($rc,Revision::DELETED_TEXT) ) { + $clink = '' . $this->skin->makeKnownLinkObj( $rc->getTitle(), '' ) . ''; + if ( !ChangesList::userCan($rc,Revision::DELETED_TEXT) ) + $showrev=false; + } else if( $rc->unpatrolled && $rc_type == RC_NEW ) { # Unpatrolled new page, give rc_id in query $clink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" ); } else { @@ -373,7 +450,10 @@ class EnhancedChangesList extends ChangesList { $querydiff = $curIdEq."&diff=$rc_this_oldid&oldid=$rc_last_oldid$rcIdQuery"; $aprops = ' tabindex="'.$baseRC->counter.'"'; $curLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['cur'], $querycur, '' ,'', $aprops ); - if( $rc_type == RC_NEW || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) { + if ( !$showrev ) { + $curLink = $this->message['cur']; + $diffLink = $this->message['diff']; + } else if( $rc_type == RC_NEW || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) { if( $rc_type != RC_NEW ) { $curLink = $this->message['cur']; } @@ -383,21 +463,27 @@ class EnhancedChangesList extends ChangesList { } # Make "last" link - if( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) { + if ( !$showrev ) { + $lastLink = $this->message['last']; + } else if( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) { $lastLink = $this->message['last']; } else { $lastLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['last'], - $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid . $rcIdQuery ); + $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid . $rcIdQuery ); + } + + # Make user links + if ( $this->isDeleted($rc,Revision::DELETED_USER) ) { + $rc->userlink = ' ' . wfMsgHtml('rev-deleted-user') . ''; + } else { + $rc->userlink = $this->skin->userLink( $rc_user, $rc_user_text ); + $rc->usertalklink = $this->skin->userToolLinks( $rc_user, $rc_user_text ); } - - $rc->userlink = $this->skin->userLink( $rc_user, $rc_user_text ); $rc->lastlink = $lastLink; $rc->curlink = $curLink; $rc->difflink = $diffLink; - $rc->usertalklink = $this->skin->userToolLinks( $rc_user, $rc_user_text ); - # Put accumulated information into the cache, for later display # Page moves go on their own line $title = $rc->getTitle(); @@ -419,10 +505,11 @@ class EnhancedChangesList extends ChangesList { */ function recentChangesBlockGroup( $block ) { global $wgLang, $wgContLang, $wgRCShowChangedSize; - $r = ''; + $r = '
      $watch
    '; # Collate list of users $isnew = false; + $namehidden = true; $unpatrolled = false; $userlinks = array(); foreach( $block as $rcObj ) { @@ -430,6 +517,11 @@ class EnhancedChangesList extends ChangesList { if( $rcObj->mAttribs['rc_new'] ) { $isnew = true; } + // if all log actions to this page were hidden, then don't + // give the name of the affected page for this block + if( !($rcObj->mAttribs['rc_deleted'] & LogViewer::DELETED_ACTION) ) { + $namehidden = false; + } $u = $rcObj->userlink; if( !isset( $userlinks[$u] ) ) { $userlinks[$u] = 0; @@ -463,24 +555,25 @@ class EnhancedChangesList extends ChangesList { $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')"; $tl = '' . $this->sideArrow() . ''; $tl .= ''; - $r .= $tl; + $r .= '
    '.$tl; # Main line - $r .= ''; - $r .= $this->recentChangesFlags( $isnew, false, $unpatrolled, ' ', $bot ); + $r .= ' '.$this->recentChangesFlags( $isnew, false, $unpatrolled, ' ', $bot ); # Timestamp - $r .= ' '.$block[0]->timestamp.' '; + $r .= ' '.$block[0]->timestamp.'  '; # Article link - $r .= $this->maybeWatchedLink( $block[0]->link, $block[0]->watched ); + if ( $namehidden ) + $r .= ' ' . wfMsgHtml('rev-deleted-event') . ''; + else + $r .= $this->maybeWatchedLink( $block[0]->link, $block[0]->watched ); $r .= $wgContLang->getDirMark(); $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id']; $currentRevision = $block[0]->mAttribs['rc_this_oldid']; if( $block[0]->mAttribs['rc_type'] != RC_LOG ) { # Changes - $n = count($block); static $nchanges = array(); if ( !isset( $nchanges[$n] ) ) { @@ -490,77 +583,94 @@ class EnhancedChangesList extends ChangesList { $r .= ' ('; - if( $isnew ) { + if( !ChangesList::userCan($rcObj,Revision::DELETED_TEXT) ) { + $r .= $nchanges[$n]; + } else if( $isnew ) { $r .= $nchanges[$n]; } else { $r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle(), $nchanges[$n], $curIdEq."&diff=$currentRevision&oldid=$oldid" ); } - $r .= ') . . '; - # Character difference $chardiff = $rcObj->getCharacterDifference( $block[ count( $block ) - 1 ]->mAttribs['rc_old_len'], $block[0]->mAttribs['rc_new_len'] ); if( $chardiff == '' ) { - $r .= ' ('; + $r .= '; '; } else { - $r .= ' ' . $chardiff. ' . . ('; + $r .= '; ' . $chardiff . ' '; } - # History - $r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle(), - $this->message['history'], $curIdEq.'&action=history' ); + $r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle(), $this->message['history'], $curIdEq.'&action=history' ); + $r .= ')'; } $r .= $users; - $r .= $this->numberofWatchingusers($block[0]->numberofWatchingusers); - $r .= "
    \n"; + if($block[0]->numberofWatchingusers > 0) { + global $wgContLang; + $r .= wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($block[0]->numberofWatchingusers)); + } + $r .= "
    \n"; # Sub-entries - $r .= '