r20446 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r20445‎ | r20446 | r20447 >
Date:15:50, 14 March 2007
Author:aaron
Status:old
Tags:
Comment:
*Merge in phase3_rev_deleted/includes
Modified paths:
  • /trunk/phase3/includes/Article.php (modified) (history)
  • /trunk/phase3/includes/ChangesList.php (modified) (history)
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/DifferenceEngine.php (modified) (history)
  • /trunk/phase3/includes/Export.php (modified) (history)
  • /trunk/phase3/includes/ImagePage.php (modified) (history)
  • /trunk/phase3/includes/Linker.php (modified) (history)
  • /trunk/phase3/includes/LogPage.php (modified) (history)
  • /trunk/phase3/includes/PageHistory.php (modified) (history)
  • /trunk/phase3/includes/RecentChange.php (modified) (history)
  • /trunk/phase3/includes/SpecialBlockip.php (modified) (history)
  • /trunk/phase3/includes/SpecialLog.php (modified) (history)
  • /trunk/phase3/includes/SpecialRecentchanges.php (modified) (history)
  • /trunk/phase3/includes/SpecialRevisiondelete.php (modified) (history)
  • /trunk/phase3/includes/SpecialUndelete.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/Article.php
@@ -1782,6 +1782,8 @@
17831783 $confirm = $wgRequest->wasPosted() &&
17841784 $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ) );
17851785 $reason = $wgRequest->getText( 'wpReason' );
 1786+ # Flag to hide all contents of the archived revisions
 1787+ $suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgUser->isAllowed('deleterevision');
17861788
17871789 # This code desperately needs to be totally rewritten
17881790
@@ -1813,7 +1815,7 @@
18141816 }
18151817
18161818 if( $confirm ) {
1817 - $this->doDelete( $reason );
 1819+ $this->doDelete( $reason, $suppress );
18181820 if( $wgRequest->getCheck( 'wpWatch' ) ) {
18191821 $this->doWatch();
18201822 } elseif( $this->mTitle->userIsWatching() ) {
@@ -1959,7 +1961,14 @@
19601962 $delcom = htmlspecialchars( wfMsg( 'deletecomment' ) );
19611963 $token = htmlspecialchars( $wgUser->editToken() );
19621964 $watch = Xml::checkLabel( wfMsg( 'watchthis' ), 'wpWatch', 'wpWatch', $wgUser->getBoolOption( 'watchdeletion' ) || $this->mTitle->userIsWatching(), array( 'tabindex' => '2' ) );
1963 -
 1965+ if ( $wgUser->isAllowed( 'deleterevision' ) ) {
 1966+ $supress = "<tr><td>&nbsp;</td><td>";
 1967+ $supress .= Xml::checkLabel( wfMsg( 'revdelete-suppress' ), 'wpSuppress', 'wpSuppress', false, array( 'tabindex' => '2' ) );
 1968+ $supress .= "</td></tr>";
 1969+ } else {
 1970+ $supress = '';
 1971+ }
 1972+
19641973 $wgOut->addHTML( "
19651974 <form id='deleteconfirm' method='post' action=\"{$formaction}\">
19661975 <table border='0'>
@@ -1971,6 +1980,7 @@
19721981 <input type='text' size='60' name='wpReason' id='wpReason' value=\"" . htmlspecialchars( $reason ) . "\" tabindex=\"1\" />
19731982 </td>
19741983 </tr>
 1984+ $supress
19751985 <tr>
19761986 <td>&nbsp;</td>
19771987 <td>$watch</td>
@@ -2009,12 +2019,12 @@
20102020 /**
20112021 * Perform a deletion and output success or failure messages
20122022 */
2013 - function doDelete( $reason ) {
 2023+ function doDelete( $reason, $suppress = false ) {
20142024 global $wgOut, $wgUser;
20152025 wfDebug( __METHOD__."\n" );
20162026
20172027 if (wfRunHooks('ArticleDelete', array(&$this, &$wgUser, &$reason))) {
2018 - if ( $this->doDeleteArticle( $reason ) ) {
 2028+ if ( $this->doDeleteArticle( $reason, $suppress ) ) {
20192029 $deleted = wfEscapeWikiText( $this->mTitle->getPrefixedText() );
20202030
20212031 $wgOut->setPagetitle( wfMsg( 'actioncomplete' ) );
@@ -2037,7 +2047,7 @@
20382048 * Deletes the article with database consistency, writes logs, purges caches
20392049 * Returns success
20402050 */
2041 - function doDeleteArticle( $reason ) {
 2051+ function doDeleteArticle( $reason, $suppress = false ) {
20422052 global $wgUseSquid, $wgDeferredUpdateList;
20432053 global $wgUseTrackbacks;
20442054
@@ -2055,6 +2065,17 @@
20562066 $u = new SiteStatsUpdate( 0, 1, -(int)$this->isCountable( $this->getContent() ), -1 );
20572067 array_push( $wgDeferredUpdateList, $u );
20582068
 2069+ / Bitfields to further supress the content
 2070+ if ( $suppress ) {
 2071+ $bitfield = 0;
 2072+ $bitfield |= Revision::DELETED_TEXT;
 2073+ $bitfield |= Revision::DELETED_COMMENT;
 2074+ $bitfield |= Revision::DELETED_USER;
 2075+ $bitfield |= Revision::DELETED_RESTRICTED;
 2076+ } else {
 2077+ $bitfield = 'rev_deleted';
 2078+ }
 2079+
20592080 / For now, shunt the revision data into the archive table.
20602081 / Text is *not* removed from the text table; bulk storage
20612082 / is left intact to avoid breaking block-compression or
@@ -2078,7 +2099,7 @@
20792100 'ar_text_id' => 'rev_text_id',
20802101 'ar_text' => '\'\'', / Be explicit to appease
20812102 'ar_flags' => '\'\'', / MySQL's "strict mode"...
2082 - 'ar_len' => 'rev_len'
 2103+ 'ar_deleted' => $bitfield
20832104 ), array(
20842105 'page_id' => $id,
20852106 'page_id = rev_page'
@@ -2119,8 +2140,9 @@
21202141 # Clear caches
21212142 Article::onArticleDelete( $this->mTitle );
21222143
2123 - # Log the deletion
2124 - $log = new LogPage( 'delete' );
 2144+ # Log the deletion, if the page was suppressed, log it at Oversight instead
 2145+ $logtype = ($suppress) ? 'oversight' : 'delete';
 2146+ $log = new LogPage( $logtype );
21252147 $log->addEntry( 'delete', $this->mTitle, $reason );
21262148
21272149 # Clear the cached article id so the interface doesn't act like we exist
@@ -2226,8 +2248,13 @@
22272249 );
22282250 }
22292251
 2252+ $target = Revision::newFromId( $s->rev_id );
 2253+ # Revision *must* be public and we don't well handle deleted edits on top
 2254+ if ( $target->isDeleted(REVISION::DELETED_TEXT) ) {
 2255+ $wgOut->setPageTitle( wfMsg('rollbackfailed') );
 2256+ $wgOut->addHTML( wfMsg( 'missingarticle' ) );
 2257+ }
22302258 # Get the edit summary
2231 - $target = Revision::newFromId( $s->rev_id );
22322259 $newComment = wfMsgForContent( 'revertpage', $target->getUserText(), $from );
22332260 $newComment = $wgRequest->getText( 'summary', $newComment );
22342261
@@ -2405,10 +2432,30 @@
24062433 ? wfMsg( 'diff' )
24072434 : $sk->makeKnownLinkObj( $this->mTitle, wfMsg( 'diff' ), 'diff=next&oldid='.$oldid );
24082435
2409 - $userlinks = $sk->userLink( $revision->getUser(), $revision->getUserText() )
2410 - . $sk->userToolLinks( $revision->getUser(), $revision->getUserText() );
 2436+ $cdel='';
 2437+ if( $wgUser->isAllowed( 'deleterevision' ) ) {
 2438+ $revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
 2439+ if( $revision->isCurrent() ) {
 2440+ / We don't handle top deleted edits too well
 2441+ $cdel = wfMsgHtml('rev-delundel');
 2442+ } else if( !$revision->userCan( Revision::DELETED_RESTRICTED ) ) {
 2443+ / If revision was hidden from sysops
 2444+ $cdel = wfMsgHtml('rev-delundel');
 2445+ } else {
 2446+ $cdel = $sk->makeKnownLinkObj( $revdel,
 2447+ wfMsgHtml('rev-delundel'),
 2448+ 'target=' . urlencode( $this->mTitle->getPrefixedDbkey() ) .
 2449+ '&oldid=' . urlencode( $oldid ) );
 2450+ / Bolden oversighted content
 2451+ if( $revision->isDeleted( Revision::DELETED_RESTRICTED ) )
 2452+ $cdel = "<strong>$cdel</strong>";
 2453+ }
 2454+ $cdel = "(<small>$cdel</small>)";
 2455+ }
24112456
2412 - $r = "\n\t\t\t\t<div id=\"mw-revision-info\">" . wfMsg( 'revision-info', $td, $userlinks ) . "</div>\n" .
 2457+ $userlinks = $sk->revUserTools( $revision, true );
 2458+
 2459+ $r = "\n\t\t\t\t<div id=\"mw-revision-info\">" . "<tt>$cdel</tt>" . wfMsg( 'revision-info', $td, $userlinks ) . "</div>\n" .
24132460 "\n\t\t\t\t<div id=\"mw-revision-nav\">" . wfMsg( 'revision-nav', $prevdiff, $prevlink, $lnk, $curdiff, $nextlink, $nextdiff ) . "</div>\n\t\t\t";
24142461 $wgOut->setSubtitle( $r );
24152462 }
Index: trunk/phase3/includes/RecentChange.php
@@ -25,6 +25,11 @@
2626 * rc_patrolled boolean whether or not someone has marked this edit as patrolled
2727 * rc_old_len integer byte length of the text before the edit
2828 * rc_new_len the same after the edit
 29+ * rc_deleted partial deletion
 30+ * rc_logid the log_id value for this log entry (or zero)
 31+ * rc_log_type the log type (or null)
 32+ * rc_log_action the log action (or null)
 33+ * rc_params log params
2934 *
3035 * mExtra:
3136 * prefixedDBkey prefixed db key, used by external app via msg queue
@@ -227,8 +232,7 @@
228233
229234 # Makes an entry in the database corresponding to an edit
230235 /*static*/ function notifyEdit( $timestamp, &$title, $minor, &$user, $comment,
231 - $oldId, $lastTimestamp, $bot = "default", $ip = '', $oldSize = 0, $newSize = 0,
232 - $newId = 0)
 236+ $oldId, $lastTimestamp, $bot="default", $ip='', $oldSize=0, $newSize=0, $newId=0)
233237 {
234238
235239 if ( $bot === 'default' ) {
@@ -263,7 +267,12 @@
264268 'rc_patrolled' => 0,
265269 'rc_new' => 0, # obsolete
266270 'rc_old_len' => $oldSize,
267 - 'rc_new_len' => $newSize
 271+ 'rc_new_len' => $newSize,
 272+ 'rc_deleted' => 0,
 273+ 'rc_logid' => 0,
 274+ 'rc_log_type' => null,
 275+ 'rc_log_action' => '',
 276+ 'rc_params' => ''
268277 );
269278
270279 $rc->mExtra = array(
@@ -284,7 +293,7 @@
285294 * @static
286295 */
287296 public static function notifyNew( $timestamp, &$title, $minor, &$user, $comment, $bot = "default",
288 - $ip='', $size = 0, $newId = 0 )
 297+ $ip='', $size=0, $newId=0 )
289298 {
290299 if ( !$ip ) {
291300 $ip = wfGetIP();
@@ -292,6 +301,7 @@
293302 $ip = '';
294303 }
295304 }
 305+
296306 if ( $bot == 'default' ) {
297307 $bot = $user->isAllowed( 'bot' );
298308 }
@@ -315,9 +325,14 @@
316326 'rc_moved_to_title' => '',
317327 'rc_ip' => $ip,
318328 'rc_patrolled' => 0,
319 - 'rc_new' => 1, # obsolete
 329+ 'rc_new' => 1, # obsolete
320330 'rc_old_len' => 0,
321 - 'rc_new_len' => $size
 331+ 'rc_new_len' => $size,
 332+ 'rc_deleted' => 0,
 333+ 'rc_logid' => 0,
 334+ 'rc_log_type' => null,
 335+ 'rc_log_action' => '',
 336+ 'rc_params' => ''
322337 );
323338
324339 $rc->mExtra = array(
@@ -339,7 +354,7 @@
340355 $ip = '';
341356 }
342357 }
343 -
 358+
344359 $rc = new RecentChange;
345360 $rc->mAttribs = array(
346361 'rc_timestamp' => $timestamp,
@@ -362,6 +377,11 @@
363378 'rc_patrolled' => 1,
364379 'rc_old_len' => NULL,
365380 'rc_new_len' => NULL,
 381+ 'rc_deleted' => 0,
 382+ 'rc_logid' => 0, # notifyMove not used anymore
 383+ 'rc_log_type' => null,
 384+ 'rc_log_action' => '',
 385+ 'rc_params' => ''
366386 );
367387
368388 $rc->mExtra = array(
@@ -380,18 +400,14 @@
381401 RecentChange::notifyMove( $timestamp, $oldTitle, $newTitle, $user, $comment, $ip, true );
382402 }
383403
384 - # A log entry is different to an edit in that previous revisions are
385 - # not kept
386 - /*static*/ function notifyLog( $timestamp, &$title, &$user, $comment, $ip='',
387 - $type, $action, $target, $logComment, $params )
 404+ # A log entry is different to an edit in that previous revisions are not kept
 405+ /*static*/ function notifyLog( $timestamp, &$title, &$user, $actionText = null, $ip='',
 406+ $type, $action, $target, $logComment, $params, $newId=0 )
388407 {
389408 if ( !$ip ) {
390409 $ip = wfGetIP();
391 - if ( !$ip ) {
392 - $ip = '';
393 - }
 410+ if ( !$ip ) $ip = '';
394411 }
395 -
396412 $rc = new RecentChange;
397413 $rc->mAttribs = array(
398414 'rc_timestamp' => $timestamp,
@@ -403,7 +419,7 @@
404420 'rc_cur_id' => $title->getArticleID(),
405421 'rc_user' => $user->getID(),
406422 'rc_user_text' => $user->getName(),
407 - 'rc_comment' => $comment,
 423+ 'rc_comment' => $logComment,
408424 'rc_this_oldid' => 0,
409425 'rc_last_oldid' => 0,
410426 'rc_bot' => $user->isAllowed( 'bot' ) ? 1 : 0,
@@ -414,6 +430,11 @@
415431 'rc_new' => 0, # obsolete
416432 'rc_old_len' => NULL,
417433 'rc_new_len' => NULL,
 434+ 'rc_deleted' => 0,
 435+ 'rc_logid' => $newId,
 436+ 'rc_log_type' => $type,
 437+ 'rc_log_action' => $action,
 438+ 'rc_params' => $params
418439 );
419440 $rc->mExtra = array(
420441 'prefixedDBkey' => $title->getPrefixedDBkey(),
@@ -460,6 +481,11 @@
461482 'rc_new' => $row->page_is_new, # obsolete
462483 'rc_old_len' => $row->rc_old_len,
463484 'rc_new_len' => $row->rc_new_len,
 485+ 'rc_deleted' => $row->rc_deleted,
 486+ 'rc_logid' => $row->rc_logid,
 487+ 'rc_log_type' => $row->rc_log_type,
 488+ 'rc_log_action' => $row->rc_log_action,
 489+ 'rc_params' => $row->rc_params
464490 );
465491
466492 $this->mExtra = array();
Index: trunk/phase3/includes/SpecialRecentchanges.php
@@ -404,7 +404,7 @@
405405 rcFormatDiff( $obj ),
406406 $title->getFullURL(),
407407 $obj->rc_timestamp,
408 - $obj->rc_user_text,
 408+ ($obj->rc_deleted & Revision::DELETED_USER) ? wfMsgHtml('rev-deleted-user') : $obj->rc_user_text,
409409 $talkpage->getFullURL()
410410 );
411411 $feed->outItem( $item );
@@ -613,15 +613,18 @@
614614 return rcFormatDiffRow( $titleObj,
615615 $row->rc_last_oldid, $row->rc_this_oldid,
616616 $timestamp,
617 - $row->rc_comment );
 617+ ($row->rc_deleted & Revision::DELETED_COMMENT) ? wfMsgHtml('rev-deleted-comment') : $row->rc_comment,
 618+ ($row->rc_deleted & Revision::DELETED_NAME) ? wfMsgHtml('rev-deleted-event') : $row->rc_actiontext );
618619 }
619620
620 -function rcFormatDiffRow( $title, $oldid, $newid, $timestamp, $comment ) {
 621+function rcFormatDiffRow( $title, $oldid, $newid, $timestamp, $comment, $actiontext='' ) {
621622 global $wgFeedDiffCutoff, $wgContLang, $wgUser;
622623 $fname = 'rcFormatDiff';
623624 wfProfileIn( $fname );
624625
625626 $skin = $wgUser->getSkin();
 627+ # log enties
 628+ if( $actiontext ) $comment = "$actiontext $comment";
626629 $completeText = '<p>' . $skin->formatComment( $comment ) . "</p>\n";
627630
628631 if( $title->getNamespace() >= 0 && $title->userCan( 'read' ) ) {
Index: trunk/phase3/includes/ImagePage.php
@@ -508,7 +508,9 @@
509509 $reason = $wgRequest->getVal( 'wpReason' );
510510 $image = $wgRequest->getVal( 'image' );
511511 $oldimage = $wgRequest->getVal( 'oldimage' );
512 -
 512+ # Flag to hide all contents of the archived revisions
 513+ $suppress = $wgRequest->getVal( 'wpSuppress' ) && $wgUser->isAllowed('deleterevision');
 514+
513515 # Only sysops can delete images. Previously ordinary users could delete
514516 # old revisions, but this is no longer the case.
515517 if ( !$wgUser->isAllowed('delete') ) {
@@ -536,7 +538,7 @@
537539 # Deleting old images doesn't require confirmation
538540 if ( !is_null( $oldimage ) || $confirm ) {
539541 if( $wgUser->matchEditToken( $wgRequest->getVal( 'wpEditToken' ), $oldimage ) ) {
540 - $this->doDelete( $reason );
 542+ $this->doDelete( $reason, $suppress );
541543 } else {
542544 $wgOut->showFatalError( wfMsg( 'sessionfailure' ) );
543545 }
@@ -557,7 +559,7 @@
558560 * Delete an image.
559561 * @param $reason User provided reason for deletion.
560562 */
561 - function doDelete( $reason ) {
 563+ function doDelete( $reason, $suppress=false ) {
562564 global $wgOut, $wgRequest;
563565
564566 $oldimage = $wgRequest->getVal( 'oldimage' );
@@ -571,12 +573,12 @@
572574 $wgOut->showUnexpectedValueError( 'oldimage', htmlspecialchars($oldimage) );
573575 return;
574576 }
575 - if ( !$this->doDeleteOldImage( $oldimage ) ) {
 577+ if ( !$this->doDeleteOldImage( $oldimage, $suppress ) ) {
576578 return;
577579 }
578580 $deleted = $oldimage;
579581 } else {
580 - $ok = $this->img->delete( $reason );
 582+ $ok = $this->img->delete( $reason, $suppress );
581583 if( !$ok ) {
582584 # If the deletion operation actually failed, bug out:
583585 $wgOut->showFileDeleteError( $this->img->getName() );
@@ -587,7 +589,7 @@
588590 # Now we remove the image description page.
589591
590592 $article = new Article( $this->mTitle );
591 - $article->doDeleteArticle( $reason ); # ignore errors
 593+ $article->doDeleteArticle( $reason, $suppress ); # ignore errors
592594
593595 $deleted = $this->img->getName();
594596 }
@@ -606,11 +608,11 @@
607609 /**
608610 * @return success
609611 */
610 - function doDeleteOldImage( $oldimage )
 612+ function doDeleteOldImage( $oldimage, $suppress=false )
611613 {
612614 global $wgOut;
613615
614 - $ok = $this->img->deleteOld( $oldimage, '' );
 616+ $ok = $this->img->deleteOld( $oldimage, '', $suppress );
615617 if( !$ok ) {
616618 # If we actually have a file and can't delete it, throw an error.
617619 # Something went awry...
Index: trunk/phase3/includes/SpecialRevisiondelete.php
@@ -2,36 +2,41 @@
33
44 /**
55 * Not quite ready for production use yet; need to fix up the restricted mode,
6 - * and provide for preservation across delete/undelete of the page.
7 - *
8 - * To try this out, set up extra permissions something like:
9 - * $wgGroupPermissions['sysop']['deleterevision'] = true;
10 - * $wgGroupPermissions['bureaucrat']['hiderevision'] = true;
 6+ * and provide for preservation across delete/undelete of images.
117 */
128
139 function wfSpecialRevisiondelete( $par = null ) {
1410 global $wgOut, $wgRequest;
1511
16 - $target = $wgRequest->getVal( 'target' );
 12+ $target = $wgRequest->getText( 'target' );
 13+ / handle our many different possible input types
1714 $oldid = $wgRequest->getIntArray( 'oldid' );
18 -
19 - $page = Title::newFromUrl( $target );
20 -
 15+ $logid = $wgRequest->getIntArray( 'logid' );
 16+ $arid = $wgRequest->getIntArray( 'arid' );
 17+ $fileid = $wgRequest->getIntArray( 'fileid' );
 18+
 19+ $page = Title::newFromUrl( $target, false );
2120 if( is_null( $page ) ) {
2221 $wgOut->showErrorPage( 'notargettitle', 'notargettext' );
2322 return;
2423 }
25 -
26 - if( is_null( $oldid ) ) {
 24+
 25+ $input_types = !is_null( $oldid ) + !is_null( $logid ) + !is_null( $arid ) + !is_null( $fileid );
 26+ if( $input_types > 1 || $input_types==0 ) {
 27+ /one target set at a time please!
2728 $wgOut->showErrorPage( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
2829 return;
2930 }
3031
31 - $form = new RevisionDeleteForm( $wgRequest );
 32+ $form = new RevisionDeleteForm( $wgRequest, $oldid, $logid, $arid, $fileid );
3233 if( $wgRequest->wasPosted() ) {
3334 $form->submit( $wgRequest );
34 - } else {
35 - $form->show( $wgRequest );
 35+ } else if( $oldid || $arid ) {
 36+ $form->showRevs( $wgRequest );
 37+ } else if( $logid ) {
 38+ $form->showEvents( $wgRequest );
 39+ } else if( $fileid ) {
 40+ $form->showImages( $wgRequest );
3641 }
3742 }
3843
@@ -40,52 +45,259 @@
4146 * @param Title $page
4247 * @param int $oldid
4348 */
44 - function __construct( $request ) {
 49+ function __construct( $request, $oldid, $logid, $arid, $fileid ) {
4550 global $wgUser;
4651
47 - $target = $request->getVal( 'target' );
48 - $this->page = Title::newFromUrl( $target );
 52+ $target = $request->getText( 'target' );
 53+ $this->page = Title::newFromUrl( $target, false );
4954
5055 $this->revisions = $request->getIntArray( 'oldid', array() );
 56+ $this->events = $request->getIntArray( 'logid', array() );
 57+ $this->archrevs = $request->getIntArray( 'arid', array() );
 58+ $this->files = $request->getIntArray( 'fileid', array() );
5159
5260 $this->skin = $wgUser->getSkin();
 61+
 62+ / log events don't have text to hide, but hiding the page name is useful
 63+ if ( $fileid ) {
 64+ $hide_text_name = array( 'revdelete-hide-image', 'wpHideImage', Image::DELETED_FILE );
 65+ $this->deletetype='file';
 66+ } else if ( $logid ) {
 67+ $hide_text_name = array( 'revdelete-hide-name', 'wpHideName', LogViewer::DELETED_ACTION );
 68+ $this->deletetype='log';
 69+ } else {
 70+ $hide_text_name = array( 'revdelete-hide-text', 'wpHideText', Revision::DELETED_TEXT );
 71+ if ( $arid ) $this->deletetype='ar';
 72+ else $this->deletetype='old';
 73+ }
5374 $this->checks = array(
54 - array( 'revdelete-hide-text', 'wpHideText', Revision::DELETED_TEXT ),
 75+ $hide_text_name,
5576 array( 'revdelete-hide-comment', 'wpHideComment', Revision::DELETED_COMMENT ),
5677 array( 'revdelete-hide-user', 'wpHideUser', Revision::DELETED_USER ),
5778 array( 'revdelete-hide-restricted', 'wpHideRestricted', Revision::DELETED_RESTRICTED ) );
5879 }
5980
6081 /**
 82+ * This sets any fields that are true to a bitfield to true on a given bitfield
 83+ * @param $bitfield, running bitfield
 84+ * @param $nbitfield, new bitfiled
 85+ */
 86+ function setBitfield( $bitfield, $nbitfield ) {
 87+ if ( $nbitfield & Revision::DELETED_TEXT) $bitfield |= Revision::DELETED_TEXT;
 88+ if ( $nbitfield & LogViewer::DELETED_ACTION) $bitfield |= LogViewer::DELETED_ACTION;
 89+ if ( $nbitfield & Image::DELETED_FILE) $bitfield |= Image::DELETED_FILE;
 90+ if ( $nbitfield & Revision::DELETED_COMMENT) $bitfield |= Revision::DELETED_COMMENT;
 91+ if ( $nbitfield & Revision::DELETED_USER) $bitfield |= Revision::DELETED_USER;
 92+ if ( $nbitfield & Revision::DELETED_RESTRICTED) $bitfield |= Revision::DELETED_RESTRICTED;
 93+ return $bitfield;
 94+ }
 95+
 96+ /**
 97+ * This lets a user set restrictions for live and archived revisions
6198 * @param WebRequest $request
6299 */
63 - function show( $request ) {
64 - global $wgOut, $wgUser;
 100+ function showRevs( $request ) {
 101+ global $wgOut, $wgUser, $action;
65102
66 - $wgOut->addWikiText( wfMsg( 'revdelete-selected', $this->page->getPrefixedText() ) );
 103+ $UserAllowed = true;
 104+ $wgOut->addWikiText( wfMsgHtml( 'revdelete-selected', $this->page->getPrefixedText() ) );
67105
 106+ $bitfields = 0;
68107 $wgOut->addHtml( "<ul>" );
69 - foreach( $this->revisions as $revid ) {
70 - $rev = Revision::newFromTitle( $this->page, $revid );
71 - if( !isset( $rev ) ) {
 108+ if ( $this->deletetype=='old') {
 109+ foreach( $this->revisions as $revid ) {
 110+ $rev = Revision::newFromTitle( $this->page, $revid );
 111+ / Hiding top revisison is bad
 112+ if( !isset( $rev ) || $rev->isCurrent() ) {
 113+ $wgOut->showErrorPage( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
 114+ return;
 115+ } else if( !$rev->userCan(Revision::DELETED_RESTRICTED) ) {
 116+ / If a rev is hidden from sysops
 117+ if ( $action != 'submit') {
 118+ $wgOut->permissionRequired( 'hiderevision' ); return;
 119+ }
 120+ $UserAllowed=false;
 121+ }
 122+ $wgOut->addHtml( $this->historyLine( $rev ) );
 123+ $bitfields = $this->setBitfield( $bitfields, $rev->mDeleted );
 124+ }
 125+ } else if ( $this->deletetype=='ar') {
 126+ $archive = new PageArchive( $this->page );
 127+ foreach( $this->archrevs as $revid ) {
 128+ $rev = $archive->getRevision('', $revid );
 129+ if( !isset( $rev ) ) {
 130+ $wgOut->showErrorPage( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
 131+ return;
 132+ } else if( !$rev->userCan(Revision::DELETED_RESTRICTED) ) {
 133+ /if a rev is hidden from sysops
 134+ if ( $action != 'submit') {
 135+ $wgOut->permissionRequired( 'hiderevision' ); return;
 136+ }
 137+ $UserAllowed=false;
 138+ }
 139+ $wgOut->addHtml( $this->historyLine( $rev ) );
 140+ $bitfields = $this->setBitfield( $bitfields, $rev->mDeleted );
 141+ }
 142+ }
 143+ $wgOut->addHtml( "</ul>" );
 144+
 145+ $wgOut->addWikiText( wfMsgHtml( 'revdelete-text' ) );
 146+ /Normal sysops can always see what they did, but can't always change it
 147+ if ( !$UserAllowed ) return;
 148+
 149+ $items = array(
 150+ wfInputLabel( wfMsgHtml( 'revdelete-log' ), 'wpReason', 'wpReason', 60 ),
 151+ wfSubmitButton( wfMsgHtml( 'revdelete-submit' ) ) );
 152+ $hidden = array(
 153+ wfHidden( 'wpEditToken', $wgUser->editToken() ),
 154+ wfHidden( 'target', $this->page->getPrefixedText() ),
 155+ wfHidden( 'type', $this->deletetype ) );
 156+ if( $this->deletetype=='old' ) {
 157+ foreach( $this->revisions as $revid ) {
 158+ $hidden[] = wfHidden( 'oldid[]', $revid );
 159+ }
 160+ } else if( $this->deletetype=='ar' ) {
 161+ foreach( $this->archrevs as $revid ) {
 162+ $hidden[] = wfHidden( 'arid[]', $revid );
 163+ }
 164+ }
 165+ $special = SpecialPage::getTitleFor( 'Revisiondelete' );
 166+ $wgOut->addHtml( wfElement( 'form', array(
 167+ 'method' => 'post',
 168+ 'action' => $special->getLocalUrl( 'action=submit' ) ),
 169+ null ) );
 170+
 171+ $wgOut->addHtml( '<fieldset><legend>' . wfMsgHtml( 'revdelete-legend' ) . '</legend>' );
 172+ / FIXME: all items checked for just one rev are checked, even if not set for the others
 173+ foreach( $this->checks as $item ) {
 174+ list( $message, $name, $field ) = $item;
 175+ $wgOut->addHtml( '<div>' .
 176+ wfCheckLabel( wfMsgHtml( $message), $name, $name, $bitfields & $field ) .
 177+ '</div>' );
 178+ }
 179+ $wgOut->addHtml( '</fieldset>' );
 180+ foreach( $items as $item ) {
 181+ $wgOut->addHtml( '<p>' . $item . '</p>' );
 182+ }
 183+ foreach( $hidden as $item ) {
 184+ $wgOut->addHtml( $item );
 185+ }
 186+
 187+ $wgOut->addHtml( '</form>' );
 188+ }
 189+
 190+ /**
 191+ * This lets a user set restrictions for archived images
 192+ * @param WebRequest $request
 193+ */
 194+ function showImages( $request ) {
 195+ global $wgOut, $wgUser, $action;
 196+
 197+ $UserAllowed = true;
 198+ $wgOut->addWikiText( wfMsgHtml( 'revdelete-selected', $this->page->getPrefixedText() ) );
 199+
 200+ $bitfields = 0;
 201+ $wgOut->addHtml( "<ul>" );
 202+ foreach( $this->files as $fileid ) {
 203+ $file = new FSarchivedFile( $this->page, $fileid );
 204+ if( !isset( $file->mId ) ) {
 205+ $wgOut->showErrorPage( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
 206+ return;
 207+ } else if( !$file->userCan(Revision::DELETED_RESTRICTED) ) {
 208+ / If a rev is hidden from sysops
 209+ if ( $action != 'submit') {
 210+ $wgOut->permissionRequired( 'hiderevision' ); return;
 211+ }
 212+ $UserAllowed=false;
 213+ }
 214+ $wgOut->addHtml( $this->uploadLine( $file ) );
 215+ $bitfields = $this->setBitfield( $bitfields, $file->mDeleted );
 216+ }
 217+ $wgOut->addHtml( "</ul>" );
 218+
 219+ $wgOut->addWikiText( wfMsgHtml( 'revdelete-text' ) );
 220+ /Normal sysops can always see what they did, but can't always change it
 221+ if ( !$UserAllowed ) return;
 222+
 223+ $items = array(
 224+ wfInputLabel( wfMsgHtml( 'revdelete-log' ), 'wpReason', 'wpReason', 60 ),
 225+ wfSubmitButton( wfMsgHtml( 'revdelete-submit' ) ) );
 226+ $hidden = array(
 227+ wfHidden( 'wpEditToken', $wgUser->editToken() ),
 228+ wfHidden( 'target', $this->page->getPrefixedText() ),
 229+ wfHidden( 'type', $this->deletetype ) );
 230+ foreach( $this->files as $fileid ) {
 231+ $hidden[] = wfHidden( 'fileid[]', $fileid );
 232+ }
 233+ $special = SpecialPage::getTitleFor( 'Revisiondelete' );
 234+ $wgOut->addHtml( wfElement( 'form', array(
 235+ 'method' => 'post',
 236+ 'action' => $special->getLocalUrl( 'action=submit' ) ),
 237+ null ) );
 238+
 239+ $wgOut->addHtml( '<fieldset><legend>' . wfMsgHtml( 'revdelete-legend' ) . '</legend>' );
 240+ / FIXME: all items checked for just one file are checked, even if not set for the others
 241+ foreach( $this->checks as $item ) {
 242+ list( $message, $name, $field ) = $item;
 243+ $wgOut->addHtml( '<div>' .
 244+ wfCheckLabel( wfMsgHtml( $message), $name, $name, $bitfields & $field ) .
 245+ '</div>' );
 246+ }
 247+ $wgOut->addHtml( '</fieldset>' );
 248+ foreach( $items as $item ) {
 249+ $wgOut->addHtml( '<p>' . $item . '</p>' );
 250+ }
 251+ foreach( $hidden as $item ) {
 252+ $wgOut->addHtml( $item );
 253+ }
 254+
 255+ $wgOut->addHtml( '</form>' );
 256+ }
 257+
 258+ /**
 259+ * This lets a user set restrictions for log items
 260+ * @param WebRequest $request
 261+ */
 262+ function showEvents( $request ) {
 263+ global $wgOut, $wgUser, $action;
 264+
 265+ $UserAllowed = true;
 266+ $wgOut->addWikiText( wfMsgHtml( 'logdelete-selected', $this->page->getPrefixedText() ) );
 267+
 268+ $bitfields = 0;
 269+ $wgOut->addHtml( "<ul>" );
 270+ foreach( $this->events as $logid ) {
 271+ $log = new LogViewer( $wgRequest );
 272+ $event = LogReader::newFromTitle( $this->page, $logid );
 273+ / Don't hide from oversight log!!!
 274+ if( !isset( $event ) || $event->log_type == 'oversight' ) {
72275 $wgOut->showErrorPage( 'revdelete-nooldid-title', 'revdelete-nooldid-text' );
73276 return;
 277+ } else if( !$log->userCan($event, Revision::DELETED_RESTRICTED) ) {
 278+ / If an event is hidden from sysops
 279+ if ( $action != 'submit') {
 280+ $wgOut->permissionRequired( 'hiderevision' ); return;
 281+ }
 282+ $UserAllowed=false;
74283 }
75 - $wgOut->addHtml( $this->historyLine( $rev ) );
76 - $bitfields[] = $rev->mDeleted; / FIXME
 284+ $wgOut->addHtml( $this->logLine( $log, $event ) );
 285+ $bitfields = $this->setBitfield( $bitfields, $event->log_deleted );
77286 }
78287 $wgOut->addHtml( "</ul>" );
79 -
80 - $wgOut->addWikiText( wfMsg( 'revdelete-text' ) );
 288+
 289+ $wgOut->addWikiText( wfMsgHtml( 'revdelete-text' ) );
 290+ /Normal sysops can always see what they did, but can't always change it
 291+ if ( !$UserAllowed ) return;
81292
82293 $items = array(
83 - wfInputLabel( wfMsg( 'revdelete-log' ), 'wpReason', 'wpReason', 60 ),
84 - wfSubmitButton( wfMsg( 'revdelete-submit' ) ) );
 294+ wfInputLabel( wfMsgHtml( 'revdelete-log' ), 'wpReason', 'wpReason', 60 ),
 295+ wfSubmitButton( wfMsgHtml( 'revdelete-submit' ) ) );
85296 $hidden = array(
86297 wfHidden( 'wpEditToken', $wgUser->editToken() ),
87 - wfHidden( 'target', $this->page->getPrefixedText() ) );
88 - foreach( $this->revisions as $revid ) {
89 - $hidden[] = wfHidden( 'oldid[]', $revid );
 298+ wfHidden( 'target', $this->page->getPrefixedText() ),
 299+ wfHidden( 'type', $this->deletetype ) );
 300+ foreach( $this->events as $logid ) {
 301+ $hidden[] = wfHidden( 'logid[]', $logid );
90302 }
91303
92304 $special = SpecialPage::getTitleFor( 'Revisiondelete' );
@@ -95,10 +307,11 @@
96308 null ) );
97309
98310 $wgOut->addHtml( '<fieldset><legend>' . wfMsgHtml( 'revdelete-legend' ) . '</legend>' );
 311+ / FIXME: all items checked for just on event are checked, even if not set for the others
99312 foreach( $this->checks as $item ) {
100313 list( $message, $name, $field ) = $item;
101314 $wgOut->addHtml( '<div>' .
102 - wfCheckLabel( wfMsg( $message), $name, $name, $rev->isDeleted( $field ) ) .
 315+ wfCheckLabel( wfMsgHtml( $message), $name, $name, $bitfields & $field ) .
103316 '</div>' );
104317 }
105318 $wgOut->addHtml( '</fieldset>' );
@@ -119,32 +332,136 @@
120333 function historyLine( $rev ) {
121334 global $wgContLang;
122335 $date = $wgContLang->timeanddate( $rev->getTimestamp() );
 336+
 337+ $difflink=''; $del = '';
 338+ if( $this->deletetype=='old' ) {
 339+ $difflink = '(' . $this->skin->makeKnownLinkObj( $this->page, wfMsgHtml('diff'),
 340+ '&diff=' . $rev->getId() . '&oldid=prev' ) . ')';
 341+ $revlink = $this->skin->makeLinkObj( $this->page, $date, 'oldid=' . $rev->getId() );
 342+ } else if( $this->deletetype=='ar' ) {
 343+ $undelete = SpecialPage::getTitleFor( 'Undelete' );
 344+ $target = $this->page->getPrefixedText();
 345+ $revlink = $this->skin->makeLinkObj( $undelete, $date, "target=$target&timestamp=" . $rev->getTimestamp() );
 346+ }
 347+
 348+ if ( $rev->isDeleted(Revision::DELETED_TEXT) ) {
 349+ $revlink = '<span class="history-deleted">'.$revlink.'</span>';
 350+ $del = ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
 351+ if ( !$rev->userCan(Revision::DELETED_TEXT) ) {
 352+ $revlink = '<span class="history-deleted">'.$date.'</span>';
 353+ }
 354+ }
 355+
123356 return
124 - "<li>" .
125 - $this->skin->makeLinkObj( $this->page, $date, 'oldid=' . $rev->getId() ) .
126 - " " .
127 - $this->skin->revUserLink( $rev ) .
128 - " " .
129 - $this->skin->revComment( $rev ) .
130 - "</li>";
 357+ "<li> $difflink $revlink " . $this->skin->revUserLink( $rev ) . " " . $this->skin->revComment( $rev ) . "$del</li>";
131358 }
132359
133360 /**
 361+ * @param Image $file
 362+ * @returns string
 363+ */
 364+ function uploadLine( $file ) {
 365+ global $wgContLang;
 366+
 367+ $target = $this->page->getPrefixedText();
 368+ $date = $wgContLang->timeanddate( $file->mTimestamp, true );
 369+
 370+ $del = '';
 371+ if ( $file->mGroup == 'deleted' ) {
 372+ $undelete = SpecialPage::getTitleFor( 'Undelete' );
 373+ $pageLink = $this->skin->makeKnownLinkObj( $undelete, $date, "target=$target&file=$file->mKey" );
 374+ } else {
 375+ $pageLink = $this->skin->makeKnownLinkObj( $this->page, $date, "file=$file->mKey" );
 376+ }
 377+ if ( $file->isDeleted(Image::DELETED_FILE) ) {
 378+ $pageLink = '<span class="history-deleted">' . $pageLink . '</span>';
 379+ $del = ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
 380+ if ( !$file->userCan(Image::DELETED_FILE) ) {
 381+ $pageLink = '<span class="history-deleted">'.$date.'</span>';
 382+ }
 383+ }
 384+
 385+ $data = wfMsgHtml( 'widthheight',
 386+ $wgContLang->formatNum( $file->mWidth ),
 387+ $wgContLang->formatNum( $file->mHeight ) ) .
 388+ ' (' . wfMsgHtml( 'nbytes', $wgContLang->formatNum( $file->mSize ) ) . ')';
 389+
 390+ return
 391+ "<li> $pageLink " . $this->skin->fileUserLink( $file ) . " $data " . $this->skin->fileComment( $file ) . "$del</li>";
 392+ }
 393+
 394+ /**
 395+ * @param Revision $rev
 396+ * @returns string
 397+ */
 398+ function logLine( $log, $event ) {
 399+ global $wgContLang;
 400+
 401+ $date = $wgContLang->timeanddate( $event->log_timestamp );
 402+ $paramArray = LogPage::extractParams( $event->log_params );
 403+
 404+ if ( !LogViewer::userCan($event,LogViewer::DELETED_ACTION) ) {
 405+ $action = '<span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
 406+ } else {
 407+ $action = LogPage::actionText( $event->log_type, $event->log_action, $this->page, $this->skin, $paramArray, true, true );
 408+ if( $event->log_deleted & LogViewer::DELETED_ACTION )
 409+ $action = '<span class="history-deleted">' . $action . '</span>';
 410+ }
 411+ return
 412+ "<li>$date" . " " . $this->skin->logUserLink( $event ) . " $action " . $this->skin->logComment( $event ) . "</li>";
 413+ }
 414+
 415+ /**
134416 * @param WebRequest $request
135417 */
136418 function submit( $request ) {
137419 $bitfield = $this->extractBitfield( $request );
138420 $comment = $request->getText( 'wpReason' );
139 - if( $this->save( $bitfield, $comment ) ) {
140 - return $this->success( $request );
141 - } else {
142 - return $this->show( $request );
143 - }
 421+
 422+ $target = $request->getText( 'target' );
 423+ $title = Title::newFromURL( $target, false );
 424+
 425+ if( $this->save( $bitfield, $comment, $title ) ) {
 426+ $this->success( $request );
 427+ } else if( $request->getCheck( 'oldid' ) || $request->getCheck( 'arid' ) ) {
 428+ return $this->showRevs( $request );
 429+ } else if( $request->getCheck( 'logid' ) ) {
 430+ return $this->showLogs( $request );
 431+ } else if( $request->getCheck( 'fileid' ) ) {
 432+ return $this->showImages( $request );
 433+ }
144434 }
145435
146436 function success( $request ) {
147437 global $wgOut;
148 - $wgOut->addWikiText( 'woo' );
 438+
 439+ $wgOut->setPagetitle( wfMsgHtml( 'actioncomplete' ) );
 440+
 441+ $target = $request->getText( 'target' );
 442+ $type = $request->getText( 'type' );
 443+
 444+ $title = Title::newFromURL( $target, false );
 445+ $name = $title->makeName( $title->getNamespace(), $title->getText() );
 446+
 447+ $logtitle = SpecialPage::getTitleFor( 'Log' );
 448+ $loglink = $this->skin->makeKnownLinkObj( $logtitle, wfMsgHtml( 'viewpagelogs' ),
 449+ wfArrayToCGI( array('page' => $name ) ) );
 450+ $histlink = $this->skin->makeKnownLinkObj( $title, wfMsgHtml( 'revhistory' ),
 451+ wfArrayToCGI( array('action' => 'history' ) ) );
 452+
 453+ if ( $title->getNamespace() > -1)
 454+ $wgOut->setSubtitle( '<p>'.$histlink.' / '.$loglink.'</p>' );
 455+
 456+ if( $type=='log' ) {
 457+ $wgOut->addWikiText( wfMsgHtml('logdelete-success', $target), false );
 458+ $this->showEvents( $request );
 459+ } else if( $type=='old' || $type=='ar' ) {
 460+ $wgOut->addWikiText( wfMsgHtml('revdelete-success', $target), false );
 461+ $this->showRevs( $request );
 462+ } else if ( $type=='file' ) {
 463+ $wgOut->addWikiText( wfMsgHtml('revdelete-success', $target), false );
 464+ $this->showImages( $request );
 465+ }
149466 }
150467
151468 /**
@@ -163,10 +480,19 @@
164481 return $bitfield;
165482 }
166483
167 - function save( $bitfield, $reason ) {
 484+ function save( $bitfield, $reason, $title ) {
168485 $dbw = wfGetDB( DB_MASTER );
169486 $deleter = new RevisionDeleter( $dbw );
170 - $deleter->setVisibility( $this->revisions, $bitfield, $reason );
 487+
 488+ if( $this->revisions ) {
 489+ return $deleter->setRevVisibility( $title, $this->revisions, $bitfield, $reason );
 490+ } else if( $this->events ) {
 491+ return $deleter->setEventVisibility( $title, $this->events, $bitfield, $reason );
 492+ } else if( $this->archrevs ) {
 493+ return $deleter->setArchiveVisibility( $title, $this->archrevs, $bitfield, $reason );
 494+ } else if( $this->files ) {
 495+ return $deleter->setFileVisibility( $title, $this->files, $bitfield, $reason );
 496+ }
171497 }
172498 }
173499
@@ -177,42 +503,192 @@
178504 }
179505
180506 /**
 507+ * @param $title, the page these events apply to
181508 * @param array $items list of revision ID numbers
182509 * @param int $bitfield new rev_deleted value
183510 * @param string $comment Comment for log records
184511 */
185 - function setVisibility( $items, $bitfield, $comment ) {
186 - $pages = array();
 512+ function setRevVisibility( $title, $items, $bitfield, $comment ) {
 513+ global $wgOut;
187514
 515+ $UserAllowedAll = true;
 516+ $pages_count = array(); $pages_revIds = array();
188517 / To work!
189518 foreach( $items as $revid ) {
190 - $rev = Revision::newFromId( $revid );
191 - if( !isset( $rev ) ) {
 519+ $rev = Revision::newFromTitle( $title, $revid );
 520+ if( !isset( $rev ) || $rev->isCurrent() ) {
192521 return false;
 522+ } else if( !$rev->userCan(Revision::DELETED_RESTRICTED) ) {
 523+ $UserAllowedAll=false;
 524+ continue;
193525 }
194 - $this->updateRevision( $rev, $bitfield );
195 - $this->updateRecentChanges( $rev, $bitfield );
196 -
 526+ $pageid = $rev->getPage();
197527 / For logging, maintain a count of revisions per page
198 - $pageid = $rev->getPage();
199 - if( isset( $pages[$pageid] ) ) {
200 - $pages[$pageid]++;
201 - } else {
202 - $pages[$pageid] = 1;
 528+ if ( !isset($pages_count[$pageid]) ) {
 529+ $pages_count[$pageid]=0;
 530+ $pages_revIds[$pageid]=array();
203531 }
 532+ / Which pages did we change anything about?
 533+ if ( $rev->mDeleted != $bitfield ) {
 534+ $pages_count[$pageid]++;
 535+ $pages_revIds[$pageid][]=$revid;
 536+
 537+ $this->updateRevision( $rev, $bitfield );
 538+ $this->updateRecentChangesEdits( $rev, $bitfield, false );
 539+ }
204540 }
205541
206542 / Clear caches...
207 - foreach( $pages as $pageid => $count ) {
208 - $title = Title::newFromId( $pageid );
209 - $this->updatePage( $title );
210 - $this->updateLog( $title, $count, $bitfield, $comment );
 543+ foreach( $pages_count as $pageid => $count ) {
 544+ /Don't log or touch if nothing changed
 545+ if ( $count > 0 ) {
 546+ $title = Title::newFromId( $pageid );
 547+ $this->updatePage( $title );
 548+ $this->updateLog( $title, $count, $bitfield, $comment, $title, 'old', $pages_revIds[$pageid] );
 549+ }
211550 }
 551+ / Where all revs allowed to be set?
 552+ if ( !$UserAllowedAll ) {
 553+ /FIXME: still might be confusing???
 554+ $wgOut->permissionRequired( 'hiderevision' ); return false;
 555+ }
212556
213557 return true;
214558 }
215559
 560+ /**
 561+ * @param $title, the page these events apply to
 562+ * @param array $items list of revision ID numbers
 563+ * @param int $bitfield new rev_deleted value
 564+ * @param string $comment Comment for log records
 565+ */
 566+ function setArchiveVisibility( $title, $items, $bitfield, $comment ) {
 567+ global $wgOut;
 568+
 569+ $UserAllowedAll = true;
 570+ $count = 0; $Id_set = array();
 571+ / To work!
 572+ $archive = new PageArchive( $title );
 573+ foreach( $items as $revid ) {
 574+ $rev = $archive->getRevision( '', $revid );
 575+ if( !isset( $rev ) ) {
 576+ return false;
 577+ } else if( !$rev->userCan(Revision::DELETED_RESTRICTED) ) {
 578+ $UserAllowedAll=false;
 579+ continue;
 580+ }
 581+ / For logging, maintain a count of revisions
 582+ if ( $rev->mDeleted != $bitfield ) {
 583+ $Id_set[]=$revid;
 584+ $count++;
 585+ }
 586+ $this->updateArchive( $rev, $bitfield );
 587+ }
 588+
 589+ / Log if something was changed
 590+ if ( $count > 0 ) {
 591+ $this->updateLog( $title, $count, $bitfield, $comment, $title, 'ar', $Id_set );
 592+ }
 593+ / Where all revs allowed to be set?
 594+ if ( !$UserAllowedAll ) {
 595+ $wgOut->permissionRequired( 'hiderevision' ); return false;
 596+ }
 597+
 598+ return true;
 599+ }
 600+
 601+ /**
 602+ * @param $title, the page these events apply to
 603+ * @param array $items list of revision ID numbers
 604+ * @param int $bitfield new rev_deleted value
 605+ * @param string $comment Comment for log records
 606+ */
 607+ function setFileVisibility( $title, $items, $bitfield, $comment ) {
 608+ global $wgOut;
 609+
 610+ $UserAllowedAll = true;
 611+ $count = 0; $Id_set = array();
 612+ / To work!
 613+ foreach( $items as $fileid ) {
 614+ $file = new FSarchivedFile( $title, $fileid );
 615+ if( !isset( $file ) ) {
 616+ return false;
 617+ } else if( !$file->userCan(Revision::DELETED_RESTRICTED) ) {
 618+ $UserAllowedAll=false;
 619+ continue;
 620+ }
 621+ / For logging, maintain a count of revisions
 622+ if ( $file->mDeleted != $bitfield ) {
 623+ $Id_set[]=$fileid;
 624+ $count++;
 625+ }
 626+ $this->updateFiles( $file, $bitfield );
 627+ }
 628+
 629+ / Log if something was changed
 630+ if ( $count > 0 ) {
 631+ $this->updateLog( $title, $count, $bitfield, $comment, $title, 'file', $Id_set );
 632+ }
 633+ / Where all revs allowed to be set?
 634+ if ( !$UserAllowedAll ) {
 635+ $wgOut->permissionRequired( 'hiderevision' ); return false;
 636+ }
 637+
 638+ return true;
 639+ }
 640+
216641 /**
 642+ * @param $title, the page these events apply to
 643+ * @param array $items list of log ID numbers
 644+ * @param int $bitfield new log_deleted value
 645+ * @param string $comment Comment for log records
 646+ */
 647+ function setEventVisibility( $title, $items, $bitfield, $comment ) {
 648+ global $wgOut;
 649+
 650+ $UserAllowedAll = true;
 651+ $logs_count = array(); $logs_Ids = array();
 652+ / To work!
 653+ foreach( $items as $logid ) {
 654+ $event = LogReader::newFromTitle( $title, $logid );
 655+ if( !isset( $event ) ) {
 656+ return false;
 657+ } else if( !LogViewer::userCan($event, Revision::DELETED_RESTRICTED) || $event->log_type == 'oversight' ) {
 658+ / Don't hide from oversight log!!!
 659+ $UserAllowedAll=false;
 660+ continue;
 661+ }
 662+ $logtype = $event->log_type;
 663+ / For logging, maintain a count of events per log type
 664+ if( !isset( $logs_count[$logtype] ) ) {
 665+ $logs_count[$logtype]=0;
 666+ $logs_Ids[$logtype]=array();
 667+ }
 668+ / Which logs did we change anything about?
 669+ if ( $event->log_deleted != $bitfield ) {
 670+ $logs_Ids[$logtype][]=$logid;
 671+ $logs_count[$logtype]++;
 672+
 673+ $this->updateLogs( $event, $bitfield );
 674+ $this->updateRecentChangesLog( $event, $bitfield, true );
 675+ }
 676+ }
 677+ foreach( $logs_count as $logtype => $count ) {
 678+ /Don't log or touch if nothing changed
 679+ if ( $count > 0 ) {
 680+ $target = SpecialPage::getTitleFor( 'Log', $logtype );
 681+ $this->updateLog( $target, $count, $bitfield, $comment, $title, 'log', $logs_Ids[$logtype] );
 682+ }
 683+ }
 684+ / Where all revs allowed to be set?
 685+ if ( !$UserAllowedAll ) {
 686+ $wgOut->permissionRequired( 'hiderevision' ); return false;
 687+ }
 688+
 689+ return true;
 690+ }
 691+
 692+ /**
217693 * Update the revision's rev_deleted field
218694 * @param Revision $rev
219695 * @param int $bitfield new rev_deleted bitfield value
@@ -225,19 +701,65 @@
226702 }
227703
228704 /**
 705+ * Update the revision's rev_deleted field
 706+ * @param Revision $rev
 707+ * @param int $bitfield new rev_deleted bitfield value
 708+ */
 709+ function updateArchive( $rev, $bitfield ) {
 710+ $this->db->update( 'archive',
 711+ array( 'ar_deleted' => $bitfield ),
 712+ array( 'ar_rev_id' => $rev->getId() ),
 713+ 'RevisionDeleter::updateArchive' );
 714+ }
 715+
 716+ /**
 717+ * Update the images's fa_deleted field
 718+ * @param Revision $file
 719+ * @param int $bitfield new rev_deleted bitfield value
 720+ */
 721+ function updateFiles( $file, $bitfield ) {
 722+ $this->db->update( 'filearchive',
 723+ array( 'fa_deleted' => $bitfield ),
 724+ array( 'fa_id' => $file->mId ),
 725+ 'RevisionDeleter::updateFiles' );
 726+ }
 727+
 728+ /**
 729+ * Update the logging log_deleted field
 730+ * @param Revision $rev
 731+ * @param int $bitfield new rev_deleted bitfield value
 732+ */
 733+ function updateLogs( $event, $bitfield ) {
 734+ $this->db->update( 'logging',
 735+ array( 'log_deleted' => $bitfield ),
 736+ array( 'log_id' => $event->log_id ),
 737+ 'RevisionDeleter::updateLogs' );
 738+ }
 739+
 740+ /**
229741 * Update the revision's recentchanges record if fields have been hidden
 742+ * @param Revision $event
 743+ * @param int $bitfield new rev_deleted bitfield value
 744+ */
 745+ function updateRecentChangesLog( $event, $bitfield ) {
 746+ $this->db->update( 'recentchanges',
 747+ array( 'rc_deleted' => $bitfield,
 748+ 'rc_patrolled' => 1),
 749+ array( 'rc_logid' => $event->log_id ),
 750+ 'RevisionDeleter::updateRecentChangesLog' );
 751+ }
 752+
 753+ /**
 754+ * Update the revision's recentchanges record if fields have been hidden
230755 * @param Revision $rev
231756 * @param int $bitfield new rev_deleted bitfield value
232757 */
233 - function updateRecentChanges( $rev, $bitfield ) {
 758+ function updateRecentChangesEdits( $rev, $bitfield ) {
234759 $this->db->update( 'recentchanges',
235 - array(
236 - 'rc_user' => ($bitfield & Revision::DELETED_USER) ? 0 : $rev->getUser(),
237 - 'rc_user_text' => ($bitfield & Revision::DELETED_USER) ? wfMsg( 'rev-deleted-user' ) : $rev->getUserText(),
238 - 'rc_comment' => ($bitfield & Revision::DELETED_COMMENT) ? wfMsg( 'rev-deleted-comment' ) : $rev->getComment() ),
239 - array(
240 - 'rc_this_oldid' => $rev->getId() ),
241 - 'RevisionDeleter::updateRecentChanges' );
 760+ array( 'rc_deleted' => $bitfield,
 761+ 'rc_patrolled' => 1),
 762+ array( 'rc_this_oldid' => $rev->getId() ),
 763+ 'RevisionDeleter::updateRecentChangesEdits' );
242764 }
243765
244766 /**
@@ -257,11 +779,25 @@
258780 * @param int $bitfield the new rev_deleted value
259781 * @param string $comment
260782 */
261 - function updateLog( $title, $count, $bitfield, $comment ) {
262 - $log = new LogPage( 'delete' );
263 - $reason = "changed $count revisions to $bitfield";
264 - $reason .= ": $comment";
265 - $log->addEntry( 'revision', $title, $reason );
 783+ function updateLog( $title, $count, $bitfield, $comment, $target, $prefix, $items = array() ) {
 784+ / Put things hidden from sysops in the oversight log
 785+ $logtype = ( $bitfield & Revision::DELETED_RESTRICTED ) ? 'oversight' : 'delete';
 786+ / Add params for effected page and ids
 787+ $params = array( $target->getPrefixedText(), $prefix, implode( ',', $items) );
 788+ $log = new LogPage( $logtype );
 789+ if ( $prefix=='log' ) {
 790+ $reason = wfMsgExt('logdelete-logaction', array('parsemag'), $count, $bitfield, $target->getPrefixedText() );
 791+ if ($comment) $reason .= ": $comment";
 792+ $log->addEntry( 'event', $title, $reason, $params );
 793+ } else if ( $prefix=='old' ) {
 794+ $reason = wfMsgExt('revdelete-logaction', array('parsemag'), $count, $bitfield );
 795+ if ($comment) $reason .= ": $comment";
 796+ $log->addEntry( 'revision', $title, $reason, $params );
 797+ } else if ( $prefix=='file' ) {
 798+ $reason = wfMsgExt('revdelete-logaction', array('parsemag'), $count, $bitfield );
 799+ if ($comment) $reason .= ": $comment";
 800+ $log->addEntry( 'file', $title, $reason, $params );
 801+ }
266802 }
267803 }
268804
Index: trunk/phase3/includes/Linker.php
@@ -830,10 +830,13 @@
831831 /**
832832 * Generate a user link if the current user is allowed to view it
833833 * @param $rev Revision object.
 834+ * @param $isPublic, bool, show only if all users can see it
834835 * @return string HTML
835836 */
836 - function revUserLink( $rev ) {
837 - if( $rev->userCan( Revision::DELETED_USER ) ) {
 837+ function revUserLink( $rev, $isPublic = false ) {
 838+ if( $rev->isDeleted( Revision::DELETED_USER ) && $isPublic ) {
 839+ $link = wfMsgHtml( 'rev-deleted-user' );
 840+ } else if( $rev->userCan( Revision::DELETED_USER ) ) {
838841 $link = $this->userLink( $rev->getRawUser(), $rev->getRawUserText() );
839842 } else {
840843 $link = wfMsgHtml( 'rev-deleted-user' );
@@ -843,27 +846,122 @@
844847 }
845848 return $link;
846849 }
 850+
 851+ /**
 852+ * Generate a user link if the current user is allowed to view it
 853+ * @param $event, log item.
 854+ * @param $isPublic, bool, show only if all users can see it
 855+ * @return string HTML
 856+ */
 857+ function logUserLink( $event, $isPublic = false ) {
 858+ if( LogViewer::isDeleted( $event, LogViewer::DELETED_USER ) && $isPublic ) {
 859+ $link = wfMsgHtml( 'rev-deleted-user' );
 860+ } else if( LogViewer::userCan( $event, LogViewer::DELETED_USER ) ) {
 861+ if ( isset($event->user_name) ) {
 862+ $link = $this->userLink( $event->log_user, $event->user_name );
 863+ } else {
 864+ $user = $event->log_user;
 865+ $link = $this->userLink( $event->log_user, User::whoIs( $user ) );
 866+ }
 867+ } else {
 868+ $link = wfMsgHtml( 'rev-deleted-user' );
 869+ }
 870+ if( LogViewer::isDeleted( $event, LogViewer::DELETED_USER ) ) {
 871+ return '<span class="history-deleted">' . $link . '</span>';
 872+ }
 873+ return $link;
 874+ }
847875
848876 /**
 877+ * Generate a user link if the current user is allowed to view it
 878+ * @param $file, filestore file
 879+ * @param $isPublic, bool, show only if all users can see it
 880+ * @return string HTML
 881+ */
 882+ function fileUserLink( $file, $isPublic = false ) {
 883+ if( $file->isDeleted( Revision::DELETED_USER ) && $isPublic ) {
 884+ $link = wfMsgHtml( 'rev-deleted-user' );
 885+ } else if( $file->userCan( Revision::DELETED_USER ) ) {
 886+ $link = $this->userLink( $file->mUser, $file->mUserText );
 887+ } else {
 888+ $link = wfMsgHtml( 'rev-deleted-user' );
 889+ }
 890+ if( $file->isDeleted( Revision::DELETED_USER ) ) {
 891+ return '<span class="history-deleted">' . $link . '</span>';
 892+ }
 893+ return $link;
 894+ }
 895+
 896+ /**
849897 * Generate a user tool link cluster if the current user is allowed to view it
850898 * @param $rev Revision object.
 899+ * @param $isPublic, bool, show only if all users can see it
851900 * @return string HTML
852901 */
853 - function revUserTools( $rev ) {
854 - if( $rev->userCan( Revision::DELETED_USER ) ) {
 902+ function revUserTools( $rev, $isPublic = false ) {
 903+ if( $rev->isDeleted( Revision::DELETED_USER ) && $isPublic ) {
 904+ $link = wfMsgHtml( 'rev-deleted-user' );
 905+ } else if( $rev->userCan( Revision::DELETED_USER ) ) {
855906 $link = $this->userLink( $rev->getRawUser(), $rev->getRawUserText() ) .
856 - ' ' .
857 - $this->userToolLinks( $rev->getRawUser(), $rev->getRawUserText() );
 907+ ' ' . $this->userToolLinks( $rev->getRawUser(), $rev->getRawUserText() );
858908 } else {
859909 $link = wfMsgHtml( 'rev-deleted-user' );
860910 }
861911 if( $rev->isDeleted( Revision::DELETED_USER ) ) {
 912+ return ' <span class="history-deleted">' . $link . '</span>';
 913+ }
 914+ return " $link";
 915+ }
 916+
 917+ /**
 918+ * Generate a user tool link cluster if the current user is allowed to view it
 919+ * @param $event, log item.
 920+ * @param $isPublic, bool, show only if all users can see it
 921+ * @return string HTML
 922+ */
 923+ function logUserTools( $event, $isPublic = false ) {
 924+ if( LogViewer::isDeleted( $event, LogViewer::DELETED_USER ) && $isPublic ) {
 925+ $link = wfMsgHtml( 'rev-deleted-user' );
 926+ } else if( LogViewer::userCan( $event, LogViewer::DELETED_USER ) ) {
 927+ if ( isset($event->user_name) ) {
 928+ $link = $this->userLink( $event->log_user, $event->user_name ) .
 929+ ' ' . $this->userToolLinks( $event->log_user, $event->user_name );
 930+ } else {
 931+ $usertext = User::whoIs( $event->log_user );
 932+ $link = $this->userLink( $event->log_user, $usertext ) .
 933+ ' ' . $this->userToolLinks( $event->log_user, $usertext );
 934+ }
 935+ } else {
 936+ $link = wfMsgHtml( 'rev-deleted-user' );
 937+ }
 938+ if( LogViewer::isDeleted( $event, LogViewer::DELETED_USER ) ) {
862939 return '<span class="history-deleted">' . $link . '</span>';
863940 }
864941 return $link;
865942 }
866 -
 943+
867944 /**
 945+ * Generate a user tool link cluster if the current user is allowed to view it
 946+ * @param $file, filestore file
 947+ * @param $isPublic, bool, show only if all users can see it
 948+ * @return string HTML
 949+ */
 950+ function fileUserTools( $file, $isPublic = false ) {
 951+ if( $file->isDeleted( Revision::DELETED_USER ) && $isPublic ) {
 952+ $link = wfMsgHtml( 'rev-deleted-user' );
 953+ } else if( $file->userCan( Revision::DELETED_USER ) ) {
 954+ $link = $this->userLink( $file->mUser, $file->mUserText ) .
 955+ $this->userToolLinks( $file->mUser, $file->mUserText );
 956+ } else {
 957+ $link = wfMsgHtml( 'rev-deleted-user' );
 958+ }
 959+ if( $file->isDeleted( Revision::DELETED_USER ) ) {
 960+ return '<span class="history-deleted">' . $link . '</span>';
 961+ }
 962+ return $link;
 963+ }
 964+
 965+ /**
868966 * This function is called by all recent changes variants, by the page history,
869967 * and by the user contributions list. It is responsible for formatting edit
870968 * comments. It escapes any HTML in the comment, but adds some CSS to format
@@ -985,21 +1083,65 @@
9861084 *
9871085 * @param Revision $rev
9881086 * @param bool $local Whether section links should refer to local page
 1087+ * @param $isPublic, show only if all users can see it
9891088 * @return string HTML
9901089 */
991 - function revComment( Revision $rev, $local = false ) {
992 - if( $rev->userCan( Revision::DELETED_COMMENT ) ) {
 1090+ function revComment( Revision $rev, $local = false, $isPublic = false ) {
 1091+ if( $rev->isDeleted( Revision::DELETED_COMMENT ) && $isPublic ) {
 1092+ $block = " <span class=\"comment\">" . wfMsgHtml( 'rev-deleted-comment' ) . "</span>";
 1093+ } else if( $rev->userCan( Revision::DELETED_COMMENT ) ) {
9931094 $block = $this->commentBlock( $rev->getRawComment(), $rev->getTitle(), $local );
9941095 } else {
995 - $block = " <span class=\"comment\">" .
996 - wfMsgHtml( 'rev-deleted-comment' ) . "</span>";
 1096+ $block = " <span class=\"comment\">" . wfMsgHtml( 'rev-deleted-comment' ) . "</span>";
9971097 }
9981098 if( $rev->isDeleted( Revision::DELETED_COMMENT ) ) {
9991099 return " <span class=\"history-deleted\">$block</span>";
10001100 }
10011101 return $block;
10021102 }
 1103+
 1104+ /**
 1105+ * Wrap and format the given event's comment block, if the current
 1106+ * user is allowed to view it.
 1107+ *
 1108+ * @param Revision $rev
 1109+ * @return string HTML
 1110+ */
 1111+ function logComment( $event, $isPublic = false ) {
 1112+ if( LogViewer::isDeleted( $event, LogViewer::DELETED_COMMENT ) && $isPublic ) {
 1113+ $block = ' ' . wfMsgHtml( 'rev-deleted-comment' );
 1114+ } else if( LogViewer::userCan( $event, LogViewer::DELETED_COMMENT ) ) {
 1115+ $block = $this->commentBlock( LogViewer::getRawComment( $event ) );
 1116+ } else {
 1117+ $block = ' ' . wfMsgHtml( 'rev-deleted-comment' );
 1118+ }
 1119+ if( LogViewer::isDeleted( $event, LogViewer::DELETED_COMMENT ) ) {
 1120+ return "<span class=\"history-deleted\">$block</span>";
 1121+ }
 1122+ return $block;
 1123+ }
10031124
 1125+ /**
 1126+ * Wrap and format the given file's comment block, if the current
 1127+ * user is allowed to view it.
 1128+ *
 1129+ * @param FileStore file object $file
 1130+ * @return string HTML
 1131+ */
 1132+ function fileComment( $file, $isPublic = false ) {
 1133+ if( $file->isDeleted( Revision::DELETED_COMMENT ) && $isPublic ) {
 1134+ $block = ' ' . wfMsgHtml( 'rev-deleted-comment' );
 1135+ } else if( $file->userCan( Revision::DELETED_COMMENT ) ) {
 1136+ $block = $this->commentBlock( $file->mDescription );
 1137+ } else {
 1138+ $block = ' ' . wfMsgHtml( 'rev-deleted-comment' );
 1139+ }
 1140+ if( $file->isDeleted( Revision::DELETED_COMMENT ) ) {
 1141+ return "<span class=\"history-deleted\">$block</span>";
 1142+ }
 1143+ return $block;
 1144+ }
 1145+
10041146 /** @todo document */
10051147 function tocIndent() {
10061148 return "\n<ul>";
Index: trunk/phase3/includes/Export.php
@@ -139,7 +139,10 @@
140140 $fname = "do_list_authors" ;
141141 wfProfileIn( $fname );
142142 $this->author_list = "<contributors>";
143 - $sql = "SELECT DISTINCT rev_user_text,rev_user FROM {$page},{$revision} WHERE page_id=rev_page AND " . $cond ;
 143+ /rev_deleted
 144+ $deleted = '(rev_deleted & '.Revision::DELETED_USER.') !=1 ';
 145+
 146+ $sql = "SELECT DISTINCT rev_user_text,rev_user FROM {$page},{$revision} WHERE page_id=rev_page AND $deleted AND " . $cond ;
144147 $result = $this->db->query( $sql, $fname );
145148 $resultset = $this->db->resultObject( $result );
146149 while( $row = $resultset->fetchObject() ) {
Index: trunk/phase3/includes/SpecialBlockip.php
@@ -45,7 +45,7 @@
4646 var $BlockAddress, $BlockExpiry, $BlockReason;
4747
4848 function IPBlockForm( $par ) {
49 - global $wgRequest;
 49+ global $wgRequest, $wgUser;
5050
5151 $this->BlockAddress = $wgRequest->getVal( 'wpBlockAddress', $wgRequest->getVal( 'ip', $par ) );
5252 $this->BlockAddress = strtr( $this->BlockAddress, '_', ' ' );
@@ -59,6 +59,8 @@
6060 $this->BlockAnonOnly = $wgRequest->getBool( 'wpAnonOnly', $byDefault );
6161 $this->BlockCreateAccount = $wgRequest->getBool( 'wpCreateAccount', $byDefault );
6262 $this->BlockEnableAutoblock = $wgRequest->getBool( 'wpEnableAutoblock', $byDefault );
 63+ # Re-check user's rights to hide names, very serious, defaults to 0
 64+ $this->BlockHideName = $wgRequest->getBool( 'wpHideName', 0 ) && $wgUser->isAllowed( 'hideuser' );
6365 }
6466
6567 function showForm( $err ) {
@@ -131,6 +133,7 @@
132134 </td>
133135 ");
134136 }
 137+
135138 $wgOut->addHTML("
136139 </tr>
137140 <tr id='wpBlockOther'>
@@ -150,31 +153,46 @@
151154 <tr id='wpAnonOnlyRow'>
152155 <td>&nbsp;</td>
153156 <td align=\"left\">
154 - " . wfCheckLabel( wfMsg( 'ipbanononly' ),
 157+ " . wfCheckLabel( wfMsgHtml( 'ipbanononly' ),
155158 'wpAnonOnly', 'wpAnonOnly', $this->BlockAnonOnly,
156 - array( 'tabindex' => 4 ) ) . "
 159+ array( 'tabindex' => '4' ) ) . "
157160 </td>
158161 </tr>
159162 <tr id='wpCreateAccountRow'>
160163 <td>&nbsp;</td>
161164 <td align=\"left\">
162 - " . wfCheckLabel( wfMsg( 'ipbcreateaccount' ),
 165+ " . wfCheckLabel( wfMsgHtml( 'ipbcreateaccount' ),
163166 'wpCreateAccount', 'wpCreateAccount', $this->BlockCreateAccount,
164 - array( 'tabindex' => 5 ) ) . "
 167+ array( 'tabindex' => '5' ) ) . "
165168 </td>
166169 </tr>
167170 <tr id='wpEnableAutoblockRow'>
168171 <td>&nbsp;</td>
169172 <td align=\"left\">
170 - " . wfCheckLabel( wfMsg( 'ipbenableautoblock' ),
 173+ " . wfCheckLabel( wfMsgHtml( 'ipbenableautoblock' ),
171174 'wpEnableAutoblock', 'wpEnableAutoblock', $this->BlockEnableAutoblock,
172 - array( 'tabindex' => 6 ) ) . "
 175+ array( 'tabindex' => '6' ) ) . "
173176 </td>
174177 </tr>
 178+ ");
 179+ / Allow some users to hide name from block log, blocklist and listusers
 180+ if ( $wgUser->isAllowed( 'hideuser' ) ) {
 181+ $wgOut->addHTML("
 182+ <tr>
 183+ <td>&nbsp;</td>
 184+ <td align=\"left\">
 185+ " . wfCheckLabel( wfMsgHtml( 'ipbhidename' ),
 186+ 'wpHideName', 'wpHideName', $this->BlockHideName,
 187+ array( 'tabindex' => '6' ) ) . "
 188+ </td>
 189+ </tr>
 190+ ");
 191+ }
 192+ $wgOut->addHTML("
175193 <tr>
176194 <td style='padding-top: 1em'>&nbsp;</td>
177195 <td style='padding-top: 1em' align=\"left\">
178 - " . Xml::submitButton( wfMsg( 'ipbsubmit' ),
 196+ " . Xml::submitButton( wfMsgHtml( 'ipbsubmit' ),
179197 array( 'name' => 'wpBlock', 'tabindex' => '7' ) ) . "
180198 </td>
181199 </tr>
@@ -191,8 +209,6 @@
192210 $this->showLogFragment( $wgOut, $user->getUserPage() );
193211 } elseif( preg_match( '/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $this->BlockAddress ) ) {
194212 $this->showLogFragment( $wgOut, Title::makeTitle( NS_USER, $this->BlockAddress ) );
195 - } elseif( preg_match( '/^\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}/', $this->BlockAddress ) ) {
196 - $this->showLogFragment( $wgOut, Title::makeTitle( NS_USER, $this->BlockAddress ) );
197213 }
198214 }
199215
@@ -200,9 +216,12 @@
201217 global $wgOut, $wgUser, $wgSysopUserBans, $wgSysopRangeBans;
202218
203219 $userId = 0;
204 - # Expand valid IPv6 addresses, usernames are left as is
205 - $this->BlockAddress = IP::sanitizeIP( $this->BlockAddress );
206 - # isIPv4() and IPv6() are used for final validation
 220+ $this->BlockAddress = trim( $this->BlockAddress );
 221+ # Expand valid IPv6 addresses
 222+ if ( IP::isIPv6( $this->BlockAddress ) ) {
 223+ $this->BlockAddress = IP::expandIP( $this->BlockAddress );
 224+ }
 225+ # The above validation is good enough that those below will suffice from here
207226 $rxIP4 = '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';
208227 $rxIP6 = '\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}:\w{1,4}';
209228 $rxIP = "($rxIP4|$rxIP6)";
@@ -283,7 +302,7 @@
284303
285304 $block = new Block( $this->BlockAddress, $userId, $wgUser->getID(),
286305 $this->BlockReason, wfTimestampNow(), 0, $expiry, $this->BlockAnonOnly,
287 - $this->BlockCreateAccount, $this->BlockEnableAutoblock );
 306+ $this->BlockCreateAccount, $this->BlockEnableAutoblock, $this->BlockHideName);
288307
289308 if (wfRunHooks('BlockIp', array(&$block, &$wgUser))) {
290309
@@ -300,8 +319,9 @@
301320 $logParams[] = $expirestr;
302321 $logParams[] = $this->blockLogFlags();
303322
304 - # Make log entry
305 - $log = new LogPage( 'block' );
 323+ # Make log entry, if the name is hidden, put it in the oversight log
 324+ $log_type = ($this->BlockHideName) ? 'oversight' : 'block';
 325+ $log = new LogPage( $log_type );
306326 $log->addEntry( 'block', Title::makeTitle( NS_USER, $this->BlockAddress ),
307327 $this->BlockReason, $logParams );
308328
Index: trunk/phase3/includes/ChangesList.php
@@ -1,5 +1,6 @@
22 <?php
33 /**
 4+ * @package MediaWiki
45 * Contain class to show various lists of change:
56 * - what's link here
67 * - related changes
@@ -8,14 +9,16 @@
910
1011 /**
1112 * @todo document
 13+ * @package MediaWiki
1214 */
1315 class RCCacheEntry extends RecentChange
1416 {
1517 var $secureName, $link;
16 - var $curlink , $difflink, $lastlink , $usertalklink , $versionlink ;
 18+ var $curlinks, $difflink, $lastlink , $usertalklink , $versionlink ;
1719 var $userlink, $timestamp, $watched;
1820
19 - function newFromParent( $rc ) {
 21+ function newFromParent( $rc )
 22+ {
2023 $rc2 = new RCCacheEntry;
2124 $rc2->mAttribs = $rc->mAttribs;
2225 $rc2->mExtra = $rc->mExtra;
@@ -24,13 +27,14 @@
2528 } ;
2629
2730 /**
 31+ * @package MediaWiki
2832 */
2933 class ChangesList {
3034 # Called by history lists and recent changes
3135 #
3236
3337 /** @todo document */
34 - function __construct( &$skin ) {
 38+ function ChangesList( &$skin ) {
3539 $this->skin =& $skin;
3640 $this->preCacheMessages();
3741 }
@@ -43,7 +47,7 @@
4448 * @return ChangesList derivative
4549 */
4650 public static function newFromUser( &$user ) {
47 - $sk = $user->getSkin();
 51+ $sk =& $user->getSkin();
4852 $list = NULL;
4953 if( wfRunHooks( 'FetchChangesList', array( &$user, &$sk, &$list ) ) ) {
5054 return $user->getOption( 'usenewrc' ) ? new EnhancedChangesList( $sk ) : new OldChangesList( $sk );
@@ -77,7 +81,7 @@
7882 : $nothing;
7983 $f .= $bot ? '<span class="bot">' . $this->message['boteditletter'] . '</span>' : $nothing;
8084 $f .= $patrolled ? '<span class="unpatrolled">!</span>' : $nothing;
81 - return $f;
 85+ return "<tt>$f</tt>";
8286 }
8387
8488 /**
@@ -103,6 +107,32 @@
104108 }
105109 }
106110
 111+ /**
 112+ * int $field one of DELETED_* bitfield constants
 113+ * @return bool
 114+ */
 115+ function isDeleted( $rc, $field ) {
 116+ return ($rc->mAttribs['rc_deleted'] & $field) == $field;
 117+ }
 118+
 119+ /**
 120+ * Determine if the current user is allowed to view a particular
 121+ * field of this revision, if it's marked as deleted.
 122+ * @param int $field
 123+ * @return bool
 124+ */
 125+ function userCan( $rc, $field ) {
 126+ if( ( $rc->mAttribs['rc_deleted'] & $field ) == $field ) {
 127+ global $wgUser;
 128+ $permission = ( $rc->mAttribs['rc_deleted'] & Revision::DELETED_RESTRICTED ) == Revision::DELETED_RESTRICTED
 129+ ? 'hiderevision'
 130+ : 'deleterevision';
 131+ wfDebug( "Checking for $permission due to $field match on $rc->mAttribs['rc_deleted']\n" );
 132+ return $wgUser->isAllowed( $permission );
 133+ } else {
 134+ return true;
 135+ }
 136+ }
107137
108138 function insertMove( &$s, $rc ) {
109139 # Diff
@@ -138,11 +168,12 @@
139169 $s .= '(' . $this->skin->makeKnownLinkObj($title, $logname ) . ')';
140170 }
141171
142 -
143172 function insertDiffHist(&$s, &$rc, $unpatrolled) {
144173 # Diff link
145 - if( $rc->mAttribs['rc_type'] == RC_NEW || $rc->mAttribs['rc_type'] == RC_LOG ) {
 174+ if( !$this->userCan($rc,Revision::DELETED_TEXT) ) {
146175 $diffLink = $this->message['diff'];
 176+ } else if( $rc->mAttribs['rc_type'] == RC_NEW || $rc->mAttribs['rc_type'] == RC_LOG) {
 177+ $diffLink = $this->message['diff'];
147178 } else {
148179 $rcidparam = $unpatrolled
149180 ? array( 'rcid' => $rc->mAttribs['rc_id'] )
@@ -172,7 +203,12 @@
173204 $params = ( $unpatrolled && $rc->mAttribs['rc_type'] == RC_NEW )
174205 ? 'rcid='.$rc->mAttribs['rc_id']
175206 : '';
176 - $articlelink = ' '. $this->skin->makeKnownLinkObj( $rc->getTitle(), '', $params );
 207+ if( $this->isDeleted($rc,Revision::DELETED_TEXT) ) {
 208+ $articlelink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '', $params );
 209+ $articlelink = '<span class="history-deleted">'.$articlelink.'</span>';
 210+ } else {
 211+ $articlelink = ' '. $this->skin->makeKnownLinkObj( $rc->getTitle(), '', $params );
 212+ }
177213 if($watched) $articlelink = '<strong>'.$articlelink.'</strong>';
178214 global $wgContLang;
179215 $articlelink .= $wgContLang->getDirMark();
@@ -188,15 +224,37 @@
189225
190226 /** Insert links to user page, user talk page and eventually a blocking link */
191227 function insertUserRelatedLinks(&$s, &$rc) {
192 - $s .= $this->skin->userLink( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
193 - $s .= $this->skin->userToolLinks( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
 228+ if ( $this->isDeleted($rc,Revision::DELETED_USER) ) {
 229+ $s .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-user') . '</span>';
 230+ } else {
 231+ $s .= $this->skin->userLink( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
 232+ $s .= $this->skin->userToolLinks( $rc->mAttribs['rc_user'], $rc->mAttribs['rc_user_text'] );
 233+ }
194234 }
195235
 236+ /** insert a formatted action */
 237+ function insertAction(&$s, &$rc) {
 238+ # Add comment
 239+ if( $rc->mAttribs['rc_type'] == RC_LOG ) {
 240+ / log action
 241+ if ( $this->isDeleted($rc,LogViewer::DELETED_ACTION) ) {
 242+ $s .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
 243+ } else {
 244+ $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 );
 245+ }
 246+ }
 247+ }
 248+
196249 /** insert a formatted comment */
197250 function insertComment(&$s, &$rc) {
198251 # Add comment
199252 if( $rc->mAttribs['rc_type'] != RC_MOVE && $rc->mAttribs['rc_type'] != RC_MOVE_OVER_REDIRECT ) {
200 - $s .= $this->skin->commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
 253+ / log comment
 254+ if ( $this->isDeleted($rc,Revision::DELETED_COMMENT) ) {
 255+ $s .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-comment') . '</span>';
 256+ } else {
 257+ $s .= $this->skin->commentBlock( $rc->mAttribs['rc_comment'], $rc->getTitle() );
 258+ }
201259 }
202260 }
203261
@@ -242,7 +300,6 @@
243301 wfProfileIn( $fname );
244302
245303 # Extract DB fields into local scope
246 - / FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
247304 extract( $rc->mAttribs );
248305
249306 # Should patrol-related stuff be shown?
@@ -252,19 +309,23 @@
253310
254311 $s .= '<li>';
255312
256 - / moved pages
 313+ / Moved pages
257314 if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
258315 $this->insertMove( $s, $rc );
259 - / log entries
260 - } elseif ( $rc_namespace == NS_SPECIAL ) {
 316+ / Log entries (old format) or log targets, and special pages
 317+ } elseif( $rc_namespace == NS_SPECIAL ) {
261318 list( $specialName, $specialSubpage ) = SpecialPage::resolveAliasWithSubpage( $rc_title );
262319 if ( $specialName == 'Log' ) {
263320 $this->insertLog( $s, $rc->getTitle(), $specialSubpage );
264321 } else {
265322 wfDebug( "Unexpected special page in recentchanges\n" );
266323 }
267 - / all other stuff
268 - } else {
 324+ / Log entries
 325+ } elseif( $rc_log_type !='' ) {
 326+ $logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL );
 327+ $this->insertLog( $s, $logtitle, $rc_log_type );
 328+ / All other stuff
 329+ } else {
269330 wfProfileIn($fname.'-page');
270331
271332 $this->insertDiffHist($s, $rc, $unpatrolled);
@@ -285,10 +346,16 @@
286347 }
287348
288349 $this->insertUserRelatedLinks($s,$rc);
 350+ $this->insertAction($s, $rc);
289351 $this->insertComment($s, $rc);
 352+
 353+ # Mark revision as deleted
 354+ if ( $this->isDeleted($rc,Revision::DELETED_TEXT) )
 355+ $s .= ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
 356+ if($rc->numberofWatchingusers > 0) {
 357+ $s .= ' ' . wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($rc->numberofWatchingusers));
 358+ }
290359
291 - $s .= rtrim(' ' . $this->numberofWatchingusers($rc->numberofWatchingusers));
292 -
293360 $s .= "</li>\n";
294361
295362 wfProfileOut( $fname.'-rest' );
@@ -313,7 +380,6 @@
314381 $rc = RCCacheEntry::newFromParent( $baseRC );
315382
316383 # Extract fields from DB into the function scope (rc_xxxx variables)
317 - / FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
318384 extract( $rc->mAttribs );
319385 $curIdEq = 'curid=' . $rc_cur_id;
320386
@@ -335,12 +401,14 @@
336402 $rc->unpatrolled = false;
337403 }
338404
 405+ $showrev=true;
339406 # Make article link
340407 if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
341408 $msg = ( $rc_type == RC_MOVE ) ? "1movedto2" : "1movedto2_redir";
342409 $clink = wfMsg( $msg, $this->skin->makeKnownLinkObj( $rc->getTitle(), '', 'redirect=no' ),
343410 $this->skin->makeKnownLinkObj( $rc->getMovedToTitle(), '' ) );
344 - } elseif( $rc_namespace == NS_SPECIAL ) {
 411+ } else if( $rc_namespace == NS_SPECIAL ) {
 412+ / Log entries (old format) and special pages
345413 list( $specialName, $logtype ) = SpecialPage::resolveAliasWithSubpage( $rc_title );
346414 if ( $specialName == 'Log' ) {
347415 # Log updates, etc
@@ -350,7 +418,16 @@
351419 wfDebug( "Unexpected special page in recentchanges\n" );
352420 $clink = '';
353421 }
354 - } elseif( $rc->unpatrolled && $rc_type == RC_NEW ) {
 422+ } elseif ( $rc_log_type !='' ) {
 423+ / Log entries
 424+ $logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL );
 425+ $logname = LogPage::logName( $rc_log_type );
 426+ $clink = '(' . $this->skin->makeKnownLinkObj($logtitle, $logname ) . ')';
 427+ } if ( $this->isDeleted($rc,Revision::DELETED_TEXT) ) {
 428+ $clink = '<span class="history-deleted">' . $this->skin->makeKnownLinkObj( $rc->getTitle(), '' ) . '</span>';
 429+ if ( !ChangesList::userCan($rc,Revision::DELETED_TEXT) )
 430+ $showrev=false;
 431+ } else if( $rc->unpatrolled && $rc_type == RC_NEW ) {
355432 # Unpatrolled new page, give rc_id in query
356433 $clink = $this->skin->makeKnownLinkObj( $rc->getTitle(), '', "rcid={$rc_id}" );
357434 } else {
@@ -373,7 +450,10 @@
374451 $querydiff = $curIdEq."&diff=$rc_this_oldid&oldid=$rc_last_oldid$rcIdQuery";
375452 $aprops = ' tabindex="'.$baseRC->counter.'"';
376453 $curLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['cur'], $querycur, '' ,'', $aprops );
377 - if( $rc_type == RC_NEW || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
 454+ if ( !$showrev ) {
 455+ $curLink = $this->message['cur'];
 456+ $diffLink = $this->message['diff'];
 457+ } else if( $rc_type == RC_NEW || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
378458 if( $rc_type != RC_NEW ) {
379459 $curLink = $this->message['cur'];
380460 }
@@ -383,21 +463,27 @@
384464 }
385465
386466 # Make "last" link
387 - if( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
 467+ if ( !$showrev ) {
 468+ $lastLink = $this->message['last'];
 469+ } else if( $rc_last_oldid == 0 || $rc_type == RC_LOG || $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
388470 $lastLink = $this->message['last'];
389471 } else {
390472 $lastLink = $this->skin->makeKnownLinkObj( $rc->getTitle(), $this->message['last'],
391 - $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid . $rcIdQuery );
 473+ $curIdEq.'&diff='.$rc_this_oldid.'&oldid='.$rc_last_oldid . $rcIdQuery );
392474 }
 475+
 476+ # Make user links
 477+ if ( $this->isDeleted($rc,Revision::DELETED_USER) ) {
 478+ $rc->userlink = ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-user') . '</span>';
 479+ } else {
 480+ $rc->userlink = $this->skin->userLink( $rc_user, $rc_user_text );
 481+ $rc->usertalklink = $this->skin->userToolLinks( $rc_user, $rc_user_text );
 482+ }
393483
394 - $rc->userlink = $this->skin->userLink( $rc_user, $rc_user_text );
395 -
396484 $rc->lastlink = $lastLink;
397485 $rc->curlink = $curLink;
398486 $rc->difflink = $diffLink;
399487
400 - $rc->usertalklink = $this->skin->userToolLinks( $rc_user, $rc_user_text );
401 -
402488 # Put accumulated information into the cache, for later display
403489 # Page moves go on their own line
404490 $title = $rc->getTitle();
@@ -419,10 +505,11 @@
420506 */
421507 function recentChangesBlockGroup( $block ) {
422508 global $wgLang, $wgContLang, $wgRCShowChangedSize;
423 - $r = '';
 509+ $r = '<table cellpadding="0" cellspacing="0"><tr>';
424510
425511 # Collate list of users
426512 $isnew = false;
 513+ $namehidden = true;
427514 $unpatrolled = false;
428515 $userlinks = array();
429516 foreach( $block as $rcObj ) {
@@ -430,6 +517,11 @@
431518 if( $rcObj->mAttribs['rc_new'] ) {
432519 $isnew = true;
433520 }
 521+ / if all log actions to this page were hidden, then don't
 522+ / give the name of the affected page for this block
 523+ if( !($rcObj->mAttribs['rc_deleted'] & LogViewer::DELETED_ACTION) ) {
 524+ $namehidden = false;
 525+ }
434526 $u = $rcObj->userlink;
435527 if( !isset( $userlinks[$u] ) ) {
436528 $userlinks[$u] = 0;
@@ -463,24 +555,25 @@
464556 $toggleLink = "javascript:toggleVisibility('$rci','$rcm','$rcl')";
465557 $tl = '<span id="'.$rcm.'"><a href="'.$toggleLink.'">' . $this->sideArrow() . '</a></span>';
466558 $tl .= '<span id="'.$rcl.'" style="display:none"><a href="'.$toggleLink.'">' . $this->downArrow() . '</a></span>';
467 - $r .= $tl;
 559+ $r .= '<td valign="top">'.$tl;
468560
469561 # Main line
470 - $r .= '<tt>';
471 - $r .= $this->recentChangesFlags( $isnew, false, $unpatrolled, '&nbsp;', $bot );
 562+ $r .= ' '.$this->recentChangesFlags( $isnew, false, $unpatrolled, '&nbsp;', $bot );
472563
473564 # Timestamp
474 - $r .= ' '.$block[0]->timestamp.' </tt>';
 565+ $r .= ' '.$block[0]->timestamp.'&nbsp;&nbsp;</td><td>';
475566
476567 # Article link
477 - $r .= $this->maybeWatchedLink( $block[0]->link, $block[0]->watched );
 568+ if ( $namehidden )
 569+ $r .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
 570+ else
 571+ $r .= $this->maybeWatchedLink( $block[0]->link, $block[0]->watched );
478572 $r .= $wgContLang->getDirMark();
479573
480574 $curIdEq = 'curid=' . $block[0]->mAttribs['rc_cur_id'];
481575 $currentRevision = $block[0]->mAttribs['rc_this_oldid'];
482576 if( $block[0]->mAttribs['rc_type'] != RC_LOG ) {
483577 # Changes
484 -
485578 $n = count($block);
486579 static $nchanges = array();
487580 if ( !isset( $nchanges[$n] ) ) {
@@ -490,77 +583,94 @@
491584
492585 $r .= ' (';
493586
494 - if( $isnew ) {
 587+ if( !ChangesList::userCan($rcObj,Revision::DELETED_TEXT) ) {
 588+ $r .= $nchanges[$n];
 589+ } else if( $isnew ) {
495590 $r .= $nchanges[$n];
496591 } else {
497592 $r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle(),
498593 $nchanges[$n], $curIdEq."&diff=$currentRevision&oldid=$oldid" );
499594 }
500595
501 - $r .= ') . . ';
502 -
503596 # Character difference
504597 $chardiff = $rcObj->getCharacterDifference( $block[ count( $block ) - 1 ]->mAttribs['rc_old_len'],
505598 $block[0]->mAttribs['rc_new_len'] );
506599 if( $chardiff == '' ) {
507 - $r .= ' (';
 600+ $r .= '; ';
508601 } else {
509 - $r .= ' ' . $chardiff. ' . . (';
 602+ $r .= '; ' . $chardiff . ' ';
510603 }
511 -
512604
513605 # History
514 - $r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle(),
515 - $this->message['history'], $curIdEq.'&action=history' );
 606+ $r .= $this->skin->makeKnownLinkObj( $block[0]->getTitle(), $this->message['history'], $curIdEq.'&action=history' );
 607+
516608 $r .= ')';
517609 }
518610
519611 $r .= $users;
520612
521 - $r .= $this->numberofWatchingusers($block[0]->numberofWatchingusers);
522 - $r .= "<br />\n";
 613+ if($block[0]->numberofWatchingusers > 0) {
 614+ global $wgContLang;
 615+ $r .= wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($block[0]->numberofWatchingusers));
 616+ }
 617+ $r .= "</td></tr></table>\n";
523618
524619 # Sub-entries
525 - $r .= '<div id="'.$rci.'" style="display:none">';
 620+ $r .= '<div id="'.$rci.'" style="display:none; font-size:95%;"><table cellpadding="0" cellspacing="0">';
526621 foreach( $block as $rcObj ) {
527622 # Get rc_xxxx variables
528 - / FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
529623 extract( $rcObj->mAttribs );
530624
531 - $r .= $this->spacerArrow();
532 - $r .= '<tt>&nbsp; &nbsp; &nbsp; &nbsp;';
 625+ #$r .= '<tr><td valign="top">'.$this->spacerArrow();
 626+ $r .= '<tr><td valign="top">'.$this->spacerIndent();
 627+ $r .= '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
533628 $r .= $this->recentChangesFlags( $rc_new, $rc_minor, $rcObj->unpatrolled, '&nbsp;', $rc_bot );
534 - $r .= '&nbsp;</tt>';
 629+ $r .= '&nbsp;&nbsp;</td><td valign="top">';
535630
536631 $o = '';
537632 if( $rc_this_oldid != 0 ) {
538633 $o = 'oldid='.$rc_this_oldid;
539634 }
 635+ # Revision link
540636 if( $rc_type == RC_LOG ) {
541 - $link = $rcObj->timestamp;
 637+ $link = $rcObj->timestamp.' ';
 638+ } else if( !ChangesList::userCan($rcObj,Revision::DELETED_TEXT) ) {
 639+ $link = '<span class="history-deleted">'.$rcObj->timestamp.'</span> ';
542640 } else {
543641 $link = $this->skin->makeKnownLinkObj( $rcObj->getTitle(), $rcObj->timestamp, $curIdEq.'&'.$o );
 642+ if( $this->isDeleted($rcObj,Revision::DELETED_TEXT) )
 643+ $link = '<span class="history-deleted">'.$link.'</span> ';
544644 }
545 - $link = '<tt>'.$link.'</tt>';
546 -
547645 $r .= $link;
548 - $r .= ' (';
549 - $r .= $rcObj->curlink;
550 - $r .= '; ';
551 - $r .= $rcObj->lastlink;
552 - $r .= ') . . ';
 646+
 647+ if ( !$rc_log_type ) {
 648+ $r .= ' (';
 649+ $r .= $rcObj->curlink;
 650+ $r .= '; ';
 651+ $r .= $rcObj->lastlink;
 652+ $r .= ')';
 653+ } else {
 654+ $logname = LogPage::logName( $rc_log_type );
 655+ $logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL );
 656+ $r .= '(' . $this->skin->makeKnownLinkObj($logtitle, $logname ) . ')';
 657+ }
 658+ $r .= ' . . ';
553659
554660 # Character diff
555661 if( $wgRCShowChangedSize ) {
556662 $r .= ( $rcObj->getCharacterDifference() == '' ? '' : $rcObj->getCharacterDifference() . ' . . ' ) ;
557663 }
558 -
 664+ # User links
559665 $r .= $rcObj->userlink;
560666 $r .= $rcObj->usertalklink;
561 - $r .= $this->skin->commentBlock( $rc_comment, $rcObj->getTitle() );
562 - $r .= "<br />\n";
 667+ / log action
 668+ parent::insertAction($r, $rcObj);
 669+ / log comment
 670+ parent::insertComment($r, $rcObj);
 671+
 672+ $r .= "</td></tr>\n";
563673 }
564 - $r .= "</div>\n";
 674+ $r .= "</table></div>\n";
565675
566676 $this->rcCacheIndex++;
567677 return $r;
@@ -617,8 +727,23 @@
618728 * @access private
619729 */
620730 function spacerArrow() {
 731+ /FIXME: problems with FF 1.5x
621732 return $this->arrow( '', ' ' );
622733 }
 734+
 735+ /**
 736+ * Generate HTML for the equivilant of a spacer image for tables
 737+ * @return string HTML <td> tag
 738+ * @access private
 739+ */
 740+ function spacerColumn() {
 741+ return '<td width="12"></td>';
 742+ }
 743+
 744+ / Adds a few spaces
 745+ function spacerIndent() {
 746+ return '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
 747+ }
623748
624749 /**
625750 * Enhanced RC ungrouped line.
@@ -628,50 +753,69 @@
629754 global $wgContLang, $wgRCShowChangedSize;
630755
631756 # Get rc_xxxx variables
632 - / FIXME: Would be good to replace this extract() call with something that explicitly initializes local variables.
633757 extract( $rcObj->mAttribs );
634758 $curIdEq = 'curid='.$rc_cur_id;
635759
636 - $r = '';
 760+ $r = '<table cellspacing="0" cellpadding="0"><tr><td>';
637761
638 - # Spacer image
639 - $r .= $this->spacerArrow();
640 -
 762+ # spacerArrow() causes issues in FF
 763+ $r .= $this->spacerColumn();
 764+ $r .= '<td valign="top">';
 765+
641766 # Flag and Timestamp
642 - $r .= '<tt>';
643 -
644767 if( $rc_type == RC_MOVE || $rc_type == RC_MOVE_OVER_REDIRECT ) {
645 - $r .= '&nbsp;&nbsp;&nbsp;';
 768+ $r .= '&nbsp;&nbsp;&nbsp;&nbsp;';
646769 } else {
647 - $r .= $this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $rcObj->unpatrolled, '&nbsp;', $rc_bot );
 770+ $r .= '&nbsp;'.$this->recentChangesFlags( $rc_type == RC_NEW, $rc_minor, $rcObj->unpatrolled, '&nbsp;', $rc_bot );
648771 }
649 - $r .= ' '.$rcObj->timestamp.' </tt>';
650 -
 772+ $r .= '&nbsp;'.$rcObj->timestamp.'&nbsp;&nbsp;</td><td>';
 773+
651774 # Article link
652 - $r .= $this->maybeWatchedLink( $rcObj->link, $rcObj->watched );
653 -
654 - # Diff
655 - $r .= ' ('. $rcObj->difflink .'; ';
656 -
657 - # Hist
658 - $r .= $this->skin->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' ) . ') . . ';
659 -
 775+ if ( $rc_log_type !='' ) {
 776+ $logtitle = Title::newFromText( "Log/$rc_log_type", NS_SPECIAL );
 777+ $logname = LogPage::logName( $rc_log_type );
 778+ $r .= '(' . $this->skin->makeKnownLinkObj($logtitle, $logname ) . ')';
 779+ / All other stuff
 780+ } else {
 781+ $r .= $this->maybeWatchedLink( $rcObj->link, $rcObj->watched );
 782+ }
 783+ if ( $rc_type != RC_LOG ) {
 784+ # Diff
 785+ $r .= ' ('. $rcObj->difflink .'; ';
 786+ # Hist
 787+ $r .= $this->skin->makeKnownLinkObj( $rcObj->getTitle(), wfMsg( 'hist' ), $curIdEq.'&action=history' ) . ')';
 788+ }
 789+ $r .= ' . . ';
 790+
660791 # Character diff
661792 if( $wgRCShowChangedSize ) {
662793 $r .= ( $rcObj->getCharacterDifference() == '' ? '' : '&nbsp;' . $rcObj->getCharacterDifference() . ' . . ' ) ;
663794 }
664795
665796 # User/talk
666 - $r .= $rcObj->userlink . $rcObj->usertalklink;
 797+ $r .= ' '.$rcObj->userlink . $rcObj->usertalklink;
667798
668799 # Comment
669800 if( $rc_type != RC_MOVE && $rc_type != RC_MOVE_OVER_REDIRECT ) {
670 - $r .= $this->skin->commentBlock( $rc_comment, $rcObj->getTitle() );
 801+ / log action
 802+ if ( $this->isDeleted($rcObj,LogViewer::DELETED_ACTION) ) {
 803+ $r .= ' <span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
 804+ } else {
 805+ $r .= ' ' . LogPage::actionText( $rc_log_type, $rc_log_action, $rcObj->getTitle(), $this->skin, LogPage::extractParams($rc_params), true, true );
 806+ }
 807+ / log comment
 808+ if ( $this->isDeleted($rcObj,LogViewer::DELETED_COMMENT) ) {
 809+ $r .= ' <span class="history-deleted">' . wfMsg('rev-deleted-comment') . '</span>';
 810+ } else {
 811+ $r .= $this->skin->commentBlock( $rc_comment, $rcObj->getTitle() );
 812+ }
671813 }
672814
673 - $r .= $this->numberofWatchingusers($rcObj->numberofWatchingusers);
 815+ if( $rcObj->numberofWatchingusers > 0 ) {
 816+ $r .= wfMsg('number_of_watching_users_RCview', $wgContLang->formatNum($rcObj->numberofWatchingusers));
 817+ }
674818
675 - $r .= "<br />\n";
 819+ $r .= "</td></tr></table>\n";
676820 return $r;
677821 }
678822
Index: trunk/phase3/includes/SpecialUndelete.php
@@ -99,7 +99,7 @@
100100 function listRevisions() {
101101 $dbr = wfGetDB( DB_SLAVE );
102102 $res = $dbr->select( 'archive',
103 - array( 'ar_minor_edit', 'ar_timestamp', 'ar_user', 'ar_user_text', 'ar_comment', 'ar_len' ),
 103+ array( 'ar_minor_edit', 'ar_timestamp', 'ar_user', 'ar_user_text', 'ar_comment', 'ar_rev_id', 'ar_deleted', 'ar_len' ),
104104 array( 'ar_namespace' => $this->title->getNamespace(),
105105 'ar_title' => $this->title->getDBkey() ),
106106 'PageArchive::listRevisions',
@@ -116,7 +116,7 @@
117117 * @return ResultWrapper
118118 * @fixme Does this belong in Image for fuller encapsulation?
119119 */
120 - function listFiles() {
 120+ function listFiles() {
121121 if( $this->title->getNamespace() == NS_IMAGE ) {
122122 $dbr = wfGetDB( DB_SLAVE );
123123 $res = $dbr->select( 'filearchive',
@@ -130,7 +130,8 @@
131131 'fa_description',
132132 'fa_user',
133133 'fa_user_text',
134 - 'fa_timestamp' ),
 134+ 'fa_timestamp',
 135+ 'fa_deleted' ),
135136 array( 'fa_name' => $this->title->getDbKey() ),
136137 __METHOD__,
137138 array( 'ORDER BY' => 'fa_timestamp DESC' ) );
@@ -151,14 +152,25 @@
152153 $rev = $this->getRevision( $timestamp );
153154 return $rev ? $rev->getText() : null;
154155 }
 156+
 157+ function getRevisionConds( $timestamp, $id ) {
 158+ if ( $id ) {
 159+ $id = intval($id);
 160+ return "ar_rev_id=$id";
 161+ } else if ( $timestamp ) {
 162+ return "ar_timestamp=$timestamp";
 163+ } else {
 164+ return 'ar_rev_id=0';
 165+ }
 166+ }
155167
156168 /**
157169 * Return a Revision object containing data for the deleted revision.
158 - * Note that the result *may* or *may not* have a null page ID.
159 - * @param string $timestamp
 170+ * Note that the result *may* have a null page ID.
 171+ * @param string $timestamp or $id
160172 * @return Revision
161173 */
162 - function getRevision( $timestamp ) {
 174+ function getRevision( $timestamp, $id=null ) {
163175 $dbr = wfGetDB( DB_SLAVE );
164176 $row = $dbr->selectRow( 'archive',
165177 array(
@@ -171,10 +183,11 @@
172184 'ar_minor_edit',
173185 'ar_flags',
174186 'ar_text_id',
 187+ 'ar_deleted',
175188 'ar_len' ),
176189 array( 'ar_namespace' => $this->title->getNamespace(),
177190 'ar_title' => $this->title->getDbkey(),
178 - 'ar_timestamp' => $dbr->timestamp( $timestamp ) ),
 191+ $this->getRevisionConds( $dbr->timestamp($timestamp), $id ) ),
179192 __METHOD__ );
180193 if( $row ) {
181194 return new Revision( array(
@@ -188,7 +201,9 @@
189202 'user_text' => $row->ar_user_text,
190203 'timestamp' => $row->ar_timestamp,
191204 'minor_edit' => $row->ar_minor_edit,
192 - 'text_id' => $row->ar_text_id ) );
 205+ 'text_id' => $row->ar_text_id,
 206+ 'deleted' => $row->ar_deleted,
 207+ 'len' => $row->ar_len) );
193208 } else {
194209 return null;
195210 }
@@ -260,7 +275,7 @@
261276 *
262277 * @return true on success.
263278 */
264 - function undelete( $timestamps, $comment = '', $fileVersions = array() ) {
 279+ function undelete( $timestamps, $comment = '', $fileVersions = array(), $Unsuppress = false) {
265280 / If both the set of text revisions and file revisions are empty,
266281 / restore everything. Otherwise, just restore the requested items.
267282 $restoreAll = empty( $timestamps ) && empty( $fileVersions );
@@ -268,17 +283,20 @@
269284 $restoreText = $restoreAll || !empty( $timestamps );
270285 $restoreFiles = $restoreAll || !empty( $fileVersions );
271286
272 - if( $restoreFiles && $this->title->getNamespace() == NS_IMAGE ) {
273 - $img = new Image( $this->title );
274 - $filesRestored = $img->restore( $fileVersions );
 287+ if( $restoreText ) {
 288+ $textRestored = $this->undeleteRevisions( $timestamps, $Unsuppress );
275289 } else {
276 - $filesRestored = 0;
 290+ $textRestored = 0;
277291 }
278292
279 - if( $restoreText ) {
280 - $textRestored = $this->undeleteRevisions( $timestamps );
 293+ if ( $restoreText && !$textRestored) {
 294+ / if the image page didn't restore right, don't restore the file either!!!
 295+ $filesRestored = 0;
 296+ } else if( $restoreFiles && $this->title->getNamespace() == NS_IMAGE ) {
 297+ $img = new Image( $this->title );
 298+ $filesRestored = $img->restore( $fileVersions, $Unsuppress );
281299 } else {
282 - $textRestored = 0;
 300+ $filesRestored = 0;
283301 }
284302
285303 / Touch the log!
@@ -286,14 +304,14 @@
287305 $log = new LogPage( 'delete' );
288306
289307 if( $textRestored && $filesRestored ) {
290 - $reason = wfMsgForContent( 'undeletedrevisions-files',
 308+ $reason = wfMsgExt( 'undeletedrevisions-files', array('parsemag'),
291309 $wgContLang->formatNum( $textRestored ),
292310 $wgContLang->formatNum( $filesRestored ) );
293311 } elseif( $textRestored ) {
294 - $reason = wfMsgForContent( 'undeletedrevisions',
 312+ $reason = wfMsgExt( 'undeletedrevisions', array('parsemag'),
295313 $wgContLang->formatNum( $textRestored ) );
296314 } elseif( $filesRestored ) {
297 - $reason = wfMsgForContent( 'undeletedfiles',
 315+ $reason = wfMsgExt( 'undeletedfiles', array('parsemag'),
298316 $wgContLang->formatNum( $filesRestored ) );
299317 } else {
300318 wfDebug( "Undelete: nothing undeleted...\n" );
@@ -315,10 +333,11 @@
316334 * @param array $timestamps Pass an empty array to restore all revisions, otherwise list the ones to undelete.
317335 * @param string $comment
318336 * @param array $fileVersions
 337+ * @param bool $Unsuppress, remove all ar_deleted/fa_deleted restrictions of seletected revs
319338 *
320339 * @return int number of revisions restored
321340 */
322 - private function undeleteRevisions( $timestamps ) {
 341+ private function undeleteRevisions( $timestamps, $Unsuppress = false ) {
323342 global $wgDBtype;
324343
325344 $restoreAll = empty( $timestamps );
@@ -362,7 +381,7 @@
363382 }
364383
365384 /**
366 - * Restore each revision...
 385+ * Select each archived revision...
367386 */
368387 $result = $dbw->select( 'archive',
369388 /* fields */ array(
@@ -375,6 +394,7 @@
376395 'ar_minor_edit',
377396 'ar_flags',
378397 'ar_text_id',
 398+ 'ar_deleted',
379399 'ar_len' ),
380400 /* WHERE */ array(
381401 'ar_namespace' => $this->title->getNamespace(),
@@ -384,15 +404,30 @@
385405 /* options */ array(
386406 'ORDER BY' => 'ar_timestamp' )
387407 );
388 - if( $dbw->numRows( $result ) < count( $timestamps ) ) {
 408+ $rev_count = $dbw->numRows( $result );
 409+ if( $rev_count < count( $timestamps ) ) {
 410+ # Remove page stub per failure
 411+ $dbw->delete( 'page', array( 'page_id' => $pageId ), __METHOD__);
389412 wfDebug( __METHOD__.": couldn't find all requested rows\n" );
390413 return false;
391414 }
392415
 416+ $ret = $dbw->resultObject( $result );
 417+ / FIXME: We don't currently handle well changing the top revision's settings
 418+ $ret->seek( $rev_count - 1 );
 419+ $last_row = $ret->fetchObject();
 420+ if ( !$Unsuppress && $last_row->ar_deleted && $last_row->ar_rev_id > $previousRevId ) {
 421+ # Remove page stub per failure
 422+ $dbw->delete( 'page', array( 'page_id' => $pageId ), __METHOD__);
 423+ wfDebug( __METHOD__.": couldn't find all requested rows or not all of them could be restored\n" );
 424+ return false;
 425+ }
 426+
393427 $revision = null;
394428 $restored = 0;
395 -
396 - while( $row = $dbw->fetchObject( $result ) ) {
 429+
 430+ $ret->seek( 0 );
 431+ while( $row = $ret->fetchObject() ) {
397432 if( $row->ar_text_id ) {
398433 / Revision was deleted in 1.5+; text is in
399434 / the regular text table, use the reference.
@@ -415,7 +450,8 @@
416451 'timestamp' => $row->ar_timestamp,
417452 'minor_edit' => $row->ar_minor_edit,
418453 'text_id' => $row->ar_text_id,
419 - 'len' => $row->ar_len
 454+ 'deleted' => ($Unsuppress) ? 0 : $row->ar_deleted,
 455+ 'len' => $row->ar_len
420456 ) );
421457 $revision->insertOn( $dbw );
422458 $restored++;
@@ -477,6 +513,7 @@
478514 $this->mRestore = $request->getCheck( 'restore' ) && $posted;
479515 $this->mPreview = $request->getCheck( 'preview' ) && $posted;
480516 $this->mComment = $request->getText( 'wpComment' );
 517+ $this->mUnsuppress = $request->getVal( 'wpUnsuppress' ) && $wgUser->isAllowed( 'oversight' );
481518
482519 if( $par != "" ) {
483520 $this->mTarget = $par;
@@ -512,21 +549,25 @@
513550 }
514551
515552 function execute() {
516 - global $wgOut;
 553+ global $wgOut, $wgUser;
517554 if ( $this->mAllowed ) {
518 - $wgOut->setPagetitle( wfMsg( "undeletepage" ) );
 555+ $wgOut->setPagetitle( wfMsgHtml( "undeletepage" ) );
519556 } else {
520 - $wgOut->setPagetitle( wfMsg( "viewdeletedpage" ) );
 557+ $wgOut->setPagetitle( wfMsgHtml( "viewdeletedpage" ) );
521558 }
522559
523560 if( is_null( $this->mTargetObj ) ) {
524 - $this->showSearchForm();
 561+ # Not all users can just browse every deleted page from the list
 562+ if ( $wgUser->isAllowed( 'browsearchive' ) ) {
 563+ $this->showSearchForm();
525564
526 - # List undeletable articles
527 - if( $this->mSearchPrefix ) {
528 - $result = PageArchive::listPagesByPrefix(
529 - $this->mSearchPrefix );
530 - $this->showList( $result );
 565+ # List undeletable articles
 566+ if( $this->mSearchPrefix ) {
 567+ $result = PageArchive::listPagesByPrefix( $this->mSearchPrefix );
 568+ $this->showList( $result );
 569+ }
 570+ } else {
 571+ $wgOut->addWikiText( wfMsgHtml( 'undelete-header' ) );
531572 }
532573 return;
533574 }
@@ -534,7 +575,14 @@
535576 return $this->showRevision( $this->mTimestamp );
536577 }
537578 if( $this->mFile !== null ) {
538 - return $this->showFile( $this->mFile );
 579+ $file = new ArchivedFile( $this->mTargetObj, '', $this->mFile );
 580+ / Check if user is allowed to see this file
 581+ if ( !$file->userCan( Image::DELETED_FILE ) ) {
 582+ $wgOut->permissionRequired( 'hiderevision' );
 583+ return false;
 584+ } else {
 585+ return $this->showFile( $this->mFile );
 586+ }
539587 }
540588 if( $this->mRestore && $this->mAction == "submit" ) {
541589 return $this->undelete();
@@ -544,7 +592,7 @@
545593
546594 function showSearchForm() {
547595 global $wgOut, $wgScript;
548 - $wgOut->addWikiText( wfMsg( 'undelete-header' ) );
 596+ $wgOut->addWikiText( wfMsgHtml( 'undelete-header' ) );
549597
550598 $wgOut->addHtml(
551599 Xml::openElement( 'form', array(
@@ -563,6 +611,7 @@
564612 '</form>' );
565613 }
566614
 615+ / Generic list of deleted pages
567616 /* private */ function showList( $result ) {
568617 global $wgLang, $wgContLang, $wgUser, $wgOut;
569618
@@ -612,11 +661,22 @@
613662 return;
614663 }
615664
 665+ if( $rev->isDeleted(Revision::DELETED_TEXT) ) {
 666+ if( !$rev->userCan(Revision::DELETED_TEXT) ) {
 667+ $wgOut->addWikiText( wfMsg( 'rev-deleted-text-permission' ) );
 668+ return;
 669+ } else {
 670+ $wgOut->addWikiText( wfMsg( 'rev-deleted-text-view' ) );
 671+ $wgOut->addHTML( '<br/>' );
 672+ / and we are allowed to see...
 673+ }
 674+ }
 675+
616676 wfRunHooks( 'UndeleteShowRevision', array( $this->mTargetObj, $rev ) );
617677
618678 if( $this->mPreview ) {
619679 $wgOut->addHtml( "<hr />\n" );
620 - $wgOut->addWikiTextTitle( $rev->getText(), $this->mTargetObj, false );
 680+ $wgOut->addWikiTextTitle( $rev->revText(), $this->mTargetObj, false );
621681 }
622682
623683 $wgOut->addHtml(
@@ -624,7 +684,7 @@
625685 'readonly' => true,
626686 'cols' => intval( $wgUser->getOption( 'cols' ) ),
627687 'rows' => intval( $wgUser->getOption( 'rows' ) ) ),
628 - $rev->getText() . "\n" ) .
 688+ $rev->revText() . "\n" ) .
629689 wfOpenElement( 'div' ) .
630690 wfOpenElement( 'form', array(
631691 'method' => 'post',
@@ -674,7 +734,7 @@
675735 /* private */ function showHistory() {
676736 global $wgLang, $wgUser, $wgOut;
677737
678 - $sk = $wgUser->getSkin();
 738+ $this->sk = $wgUser->getSkin();
679739 if ( $this->mAllowed ) {
680740 $wgOut->setPagetitle( wfMsg( "undeletepage" ) );
681741 } else {
@@ -690,9 +750,10 @@
691751 }
692752 */
693753 if ( $this->mAllowed ) {
694 - $wgOut->addWikiText( wfMsg( "undeletehistory" ) );
 754+ $wgOut->addWikiText( '<p>' . wfMsgHtml( "undeletehistory" ) . '</p>' );
 755+ $wgOut->addHtml( '<p>' . wfMsgHtml( "undeleterevdel" ) . '</p>' );
695756 } else {
696 - $wgOut->addWikiText( wfMsg( "undeletehistorynoadmin" ) );
 757+ $wgOut->addWikiText( wfMsgHtml( "undeletehistorynoadmin" ) );
697758 }
698759
699760 # List all stored revisions
@@ -738,7 +799,16 @@
739800 array( 'page' => $this->mTargetObj->getPrefixedText(),
740801 'type' => 'delete' ) ) ) );
741802 $logViewer->showList( $wgOut );
742 -
 803+ # Show relevant lines from the oversight log if user is allowed to see it:
 804+ if ( $wgUser->isAllowed( 'oversight' ) ) {
 805+ $wgOut->addHTML( "<h2>" . htmlspecialchars( LogPage::logName( 'oversight' ) ) . "</h2>\n" );
 806+ $logViewer = new LogViewer(
 807+ new LogReader(
 808+ new FauxRequest(
 809+ array( 'page' => $this->mTargetObj->getPrefixedText(),
 810+ 'type' => 'oversight' ) ) ) );
 811+ $logViewer->showList( $wgOut );
 812+ }
743813 if( $this->mAllowed && ( $haveRevisions || $haveFiles ) ) {
744814 # Format the user-visible controls (comment field, submission button)
745815 # in a nice little table
@@ -746,6 +816,10 @@
747817 $table .= '<td colspan="2">' . wfMsgWikiHtml( 'undeleteextrahelp' ) . '</td></tr><tr>';
748818 $table .= '<td align="right"><strong>' . wfMsgHtml( 'undeletecomment' ) . '</strong></td>';
749819 $table .= '<td>' . wfInput( 'wpComment', 50, $this->mComment ) . '</td>';
 820+ if ( $wgUser->isAllowed( 'oversight' ) ) {
 821+ $table .= '</tr><tr><td>&nbsp;</td><td>';
 822+ $table .= Xml::checkLabel( wfMsg( 'revdelete-unsuppress' ), 'wpUnsuppress', 'wpUnsuppress', false, array( 'tabindex' => '2' ) );
 823+ }
750824 $table .= '</tr><tr><td>&nbsp;</td><td>';
751825 $table .= wfSubmitButton( wfMsg( 'undeletebtn' ), array( 'name' => 'restore' ) );
752826 $table .= wfElement( 'input', array( 'type' => 'reset', 'value' => wfMsg( 'undeletereset' ) ) );
@@ -761,26 +835,48 @@
762836 $target = urlencode( $this->mTarget );
763837 while( $row = $revisions->fetchObject() ) {
764838 $ts = wfTimestamp( TS_MW, $row->ar_timestamp );
 839+ / We don't handle top edits with rev_deleted
765840 if ( $this->mAllowed ) {
766 - $checkBox = wfCheck( "ts$ts" );
767 - $pageLink = $sk->makeKnownLinkObj( $titleObj,
768 - $wgLang->timeanddate( $ts, true ),
769 - "target=$target&timestamp=$ts" );
 841+ $checkBox = wfCheck( "ts$ts", false );
 842+ $titleObj = SpecialPage::getTitleFor( "Undelete" );
 843+ $pageLink = $this->getPageLink( $row, $titleObj, $ts, $target );
770844 } else {
771845 $checkBox = '';
772846 $pageLink = $wgLang->timeanddate( $ts, true );
773847 }
774 - $userLink = $sk->userLink( $row->ar_user, $row->ar_user_text ) . $sk->userToolLinks( $row->ar_user, $row->ar_user_text );
 848+ $userLink = $this->getUser( $row );
775849 $stxt = '';
776850 if (!is_null($size = $row->ar_len)) {
777851 if ($size == 0)
778852 $stxt = wfMsgHtml('historyempty');
779 - else
 853+ else
780854 $stxt = wfMsgHtml('historysize', $wgLang->formatNum( $size ) );
781855 }
782 - $comment = $sk->commentBlock( $row->ar_comment );
783 - $wgOut->addHTML( "<li>$checkBox $pageLink . . $userLink $stxt $comment</li>\n" );
784 -
 856+ $comment = $this->getComment( $row );
 857+ $rd='';
 858+ if( $wgUser->isAllowed( 'deleterevision' ) ) {
 859+ $revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
 860+ if( !$this->userCan( $row, Revision::DELETED_RESTRICTED ) ) {
 861+ / If revision was hidden from sysops
 862+ $del = wfMsgHtml( 'rev-delundel' );
 863+ } else {
 864+ $del = $this->sk->makeKnownLinkObj( $revdel,
 865+ wfMsg( 'rev-delundel' ),
 866+ 'target=' . urlencode( $this->mTarget ) .
 867+ '&arid=' . urlencode( $row->ar_rev_id ) );
 868+ / Bolden oversighted content
 869+ if( $this->isDeleted( $row, Revision::DELETED_RESTRICTED ) )
 870+ $del = "<strong>$del</strong>";
 871+ }
 872+ $rd = "<tt>(<small>$del</small>)</tt>";
 873+ }
 874+
 875+ $dflag='';
 876+ if( $this->isDeleted( $row, Revision::DELETED_TEXT ) )
 877+ $dflag = ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
 878+
 879+ / Do we still need checkboxes?
 880+ $wgOut->addHTML( "<li>$checkBox $rd $pageLink . . $userLink $stxt $comment$dflag</li>\n" );
785881 }
786882 $revisions->free();
787883 $wgOut->addHTML("</ul>");
@@ -795,17 +891,21 @@
796892 while( $row = $files->fetchObject() ) {
797893 $ts = wfTimestamp( TS_MW, $row->fa_timestamp );
798894 if ( $this->mAllowed && $row->fa_storage_key ) {
799 - $checkBox = wfCheck( "fileid" . $row->fa_id );
 895+ if ( !$this->userCan( $row, Revision::DELETED_RESTRICTED ) )
 896+ / Grey out boxes to files restricted beyond this user.
 897+ / In the future, all image storage may use FileStore, allowing
 898+ / for such items to be restored and retain their fa_deleted status
 899+ $checkBox = wfCheck( "", false, array("disabled" => "disabled") );
 900+ else
 901+ $checkBox = wfCheck( "fileid" . $row->fa_id );
800902 $key = urlencode( $row->fa_storage_key );
801903 $target = urlencode( $this->mTarget );
802 - $pageLink = $sk->makeKnownLinkObj( $titleObj,
803 - $wgLang->timeanddate( $ts, true ),
804 - "target=$target&file=$key" );
 904+ $pageLink = $this->getFileLink( $row, $titleObj, $ts, $target, $key );
805905 } else {
806906 $checkBox = '';
807907 $pageLink = $wgLang->timeanddate( $ts, true );
808908 }
809 - $userLink = $sk->userLink( $row->fa_user, $row->fa_user_text ) . $sk->userToolLinks( $row->fa_user, $row->fa_user_text );
 909+ $userLink = $this->getFileUser( $row );
810910 $data =
811911 wfMsgHtml( 'widthheight',
812912 $wgLang->formatNum( $row->fa_width ),
@@ -813,8 +913,25 @@
814914 ' (' .
815915 wfMsgHtml( 'nbytes', $wgLang->formatNum( $row->fa_size ) ) .
816916 ')';
817 - $comment = $sk->commentBlock( $row->fa_description );
818 - $wgOut->addHTML( "<li>$checkBox $pageLink . . $userLink $data $comment</li>\n" );
 917+ $comment = $this->getFileComment( $row );
 918+ $rd='';
 919+ if( $wgUser->isAllowed( 'deleterevision' ) ) {
 920+ $revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
 921+ if( !$this->userCan( $row, Image::DELETED_RESTRICTED ) ) {
 922+ / If revision was hidden from sysops
 923+ $del = wfMsgHtml( 'rev-delundel' );
 924+ } else {
 925+ $del = $this->sk->makeKnownLinkObj( $revdel,
 926+ wfMsg( 'rev-delundel' ),
 927+ 'target=' . urlencode( $this->mTarget ) .
 928+ '&fileid=' . urlencode( $row->fa_id ) );
 929+ / Bolden oversighted content
 930+ if( $this->isDeleted( $row, Image::DELETED_RESTRICTED ) )
 931+ $del = "<strong>$del</strong>";
 932+ }
 933+ $rd = "<tt>(<small>$del</small>)</tt>";
 934+ }
 935+ $wgOut->addHTML( "<li>$checkBox $rd $pageLink . . $userLink $data $comment</li>\n" );
819936 }
820937 $files->free();
821938 $wgOut->addHTML( "</ul>" );
@@ -830,6 +947,143 @@
831948 return true;
832949 }
833950
 951+ /**
 952+ * Fetch revision text link if it's available to all users
 953+ * @return string
 954+ */
 955+ function getPageLink( $row, $titleObj, $ts, $target ) {
 956+ global $wgLang;
 957+
 958+ if ( !$this->userCan($row, Revision::DELETED_TEXT) ) {
 959+ return '<span class="history-deleted">' . $wgLang->timeanddate( $ts, true ) . '</span>';
 960+ } else {
 961+ $link = $this->sk->makeKnownLinkObj( $titleObj, $wgLang->timeanddate( $ts, true ), "target=$target&timestamp=$ts" );
 962+ if ( $this->isDeleted($row, Revision::DELETED_TEXT) )
 963+ $link = '<span class="history-deleted">' . $link . '</span>';
 964+ return $link;
 965+ }
 966+ }
 967+
 968+ /**
 969+ * Fetch image view link if it's available to all users
 970+ * @return string
 971+ */
 972+ function getFileLink( $row, $titleObj, $ts, $target, $key ) {
 973+ global $wgLang;
 974+
 975+ if ( !$this->userCan($row, Image::DELETED_FILE) ) {
 976+ return '<span class="history-deleted">' . $wgLang->timeanddate( $ts, true ) . '</span>';
 977+ } else {
 978+ $link = $this->sk->makeKnownLinkObj( $titleObj, $wgLang->timeanddate( $ts, true ), "target=$target&file=$key" );
 979+ if ( $this->isDeleted($row, Image::DELETED_FILE) )
 980+ $link = '<span class="history-deleted">' . $link . '</span>';
 981+ return $link;
 982+ }
 983+ }
 984+
 985+ /**
 986+ * Fetch revision's user id if it's available to this user
 987+ * @return string
 988+ */
 989+ function getUser( $row ) {
 990+ if ( !$this->userCan($row, Revision::DELETED_USER) ) {
 991+ return '<span class="history-deleted">' . wfMsgHtml( 'rev-deleted-user' ) . '</span>';
 992+ } else {
 993+ $link = $this->sk->userLink( $row->ar_user, $row->ar_user_text ) . $this->sk->userToolLinks( $row->ar_user, $row->ar_user_text );
 994+ if ( $this->isDeleted($row, Revision::DELETED_USER) )
 995+ $link = '<span class="history-deleted">' . $link . '</span>';
 996+ return $link;
 997+ }
 998+ }
 999+
 1000+ /**
 1001+ * Fetch file's user id if it's available to this user
 1002+ * @return string
 1003+ */
 1004+ function getFileUser( $row ) {
 1005+ if ( !$this->userCan($row, Image::DELETED_USER) ) {
 1006+ return '<span class="history-deleted">' . wfMsgHtml( 'rev-deleted-user' ) . '</span>';
 1007+ } else {
 1008+ $link = $this->sk->userLink( $row->fa_user, $row->fa_user_text ) . $this->sk->userToolLinks( $row->fa_user, $row->fa_user_text );
 1009+ if ( $this->isDeleted($row, Image::DELETED_USER) )
 1010+ $link = '<span class="history-deleted">' . $link . '</span>';
 1011+ return $link;
 1012+ }
 1013+ }
 1014+
 1015+ /**
 1016+ * Fetch revision comment if it's available to this user
 1017+ * @return string
 1018+ */
 1019+ function getComment( $row ) {
 1020+ if ( !$this->userCan($row, Revision::DELETED_COMMENT) ) {
 1021+ return '<span class="history-deleted"><span class="comment">' . wfMsgHtml( 'rev-deleted-comment' ) . '</span></span>';
 1022+ } else {
 1023+ $link = $this->sk->commentBlock( $row->ar_comment );
 1024+ if ( $this->isDeleted($row, Revision::DELETED_COMMENT) )
 1025+ $link = '<span class="history-deleted">' . $link . '</span>';
 1026+ return $link;
 1027+ }
 1028+ }
 1029+
 1030+ /**
 1031+ * Fetch file upload comment if it's available to this user
 1032+ * @return string
 1033+ */
 1034+ function getFileComment( $row ) {
 1035+ if ( !$this->userCan($row, Image::DELETED_COMMENT) ) {
 1036+ return '<span class="history-deleted"><span class="comment">' . wfMsgHtml( 'rev-deleted-comment' ) . '</span></span>';
 1037+ } else {
 1038+ $link = $this->sk->commentBlock( $row->fa_description );
 1039+ if ( $this->isDeleted($row, Image::DELETED_COMMENT) )
 1040+ $link = '<span class="history-deleted">' . $link . '</span>';
 1041+ return $link;
 1042+ }
 1043+ }
 1044+
 1045+ /**
 1046+ * int $field one of DELETED_* bitfield constants
 1047+ * for file or revision rows
 1048+ * @return bool
 1049+ */
 1050+ function isDeleted( $row, $field ) {
 1051+ if ( isset($row->ar_deleted) )
 1052+ / page revisions
 1053+ return ($row->ar_deleted & $field) == $field;
 1054+ else if ( isset($row->fa_deleted) )
 1055+ / files
 1056+ return ($row->fa_deleted & $field) == $field;
 1057+ return false;
 1058+ }
 1059+
 1060+ /**
 1061+ * Determine if the current user is allowed to view a particular
 1062+ * field of this revision, if it's marked as deleted.
 1063+ * @param int $field
 1064+ * @return bool
 1065+ */
 1066+ function userCan( $row, $field ) {
 1067+ global $wgUser;
 1068+
 1069+ if( isset($row->ar_deleted) && ($row->ar_deleted & $field) == $field ) {
 1070+ / page revisions
 1071+ $permission = ( $row->ar_deleted & Revision::DELETED_RESTRICTED ) == Revision::DELETED_RESTRICTED
 1072+ ? 'hiderevision'
 1073+ : 'deleterevision';
 1074+ wfDebug( "Checking for $permission due to $field match on $row->ar_deleted\n" );
 1075+ return $wgUser->isAllowed( $permission );
 1076+ } else if( isset($row->fa_deleted) && ($row->fa_deleted & $field) == $field ) {
 1077+ / files
 1078+ $permission = ( $row->fa_deleted & Image::DELETED_RESTRICTED ) == Image::DELETED_RESTRICTED
 1079+ ? 'hiderevision'
 1080+ : 'deleterevision';
 1081+ wfDebug( "Checking for $permission due to $field match on $row->fa_deleted\n" );
 1082+ return $wgUser->isAllowed( $permission );
 1083+ } else {
 1084+ return true;
 1085+ }
 1086+ }
 1087+
8341088 function undelete() {
8351089 global $wgOut, $wgUser;
8361090 if( !is_null( $this->mTargetObj ) ) {
@@ -838,16 +1092,22 @@
8391093 $ok = $archive->undelete(
8401094 $this->mTargetTimestamp,
8411095 $this->mComment,
842 - $this->mFileVersions );
843 -
 1096+ $this->mFileVersions,
 1097+ $this->mUnsuppress );
8441098 if( $ok ) {
8451099 $skin = $wgUser->getSkin();
8461100 $link = $skin->makeKnownLinkObj( $this->mTargetObj );
8471101 $wgOut->addHtml( wfMsgWikiHtml( 'undeletedpage', $link ) );
8481102 return true;
8491103 }
 1104+ / Give user some idea of what is going on ...
 1105+ / This can happen if the top revision would end up being deleted
 1106+ $wgOut->addHtml( '<p>' . wfMsgHtml( "cannotundelete" ) . '</p>' );
 1107+ $wgOut->addHtml( '<p>' . wfMsgHtml( "undeleterevdel" ) . '</p>' );
 1108+ $wgOut->returnToMain( false, $this->mTargetObj );
 1109+ return false;
8501110 }
851 - $wgOut->showFatalError( wfMsg( "cannotundelete" ) );
 1111+ $wgOut->showFatalError( wfMsgHtml( "cannotundelete" ) );
8521112 return false;
8531113 }
8541114 }
Index: trunk/phase3/includes/DifferenceEngine.php
@@ -174,14 +174,49 @@
175175 $newminor = wfElement( 'span', array( 'class' => 'minor' ),
176176 wfMsg( 'minoreditletter') ) . ' ';
177177 }
 178+
 179+ $rdel = ''; $ldel = '';
 180+ if( $wgUser->isAllowed( 'deleterevision' ) ) {
 181+ $revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
 182+ if( !$this->mOldRev->userCan( Revision::DELETED_RESTRICTED ) ) {
 183+ / If revision was hidden from sysops
 184+ $ldel = wfMsgHtml('rev-delundel');
 185+ } else {
 186+ $ldel = $sk->makeKnownLinkObj( $revdel,
 187+ wfMsgHtml('rev-delundel'),
 188+ 'target=' . urlencode( $this->mOldRev->mTitle->getPrefixedDbkey() ) .
 189+ '&oldid=' . urlencode( $this->mOldRev->getId() ) );
 190+ / Bolden oversighted content
 191+ if( $this->mOldRev->isDeleted( Revision::DELETED_RESTRICTED ) )
 192+ $ldel = "<strong>$ldel</strong>";
 193+ }
 194+ $ldel = "&nbsp;&nbsp;&nbsp;<tt>(<small>$ldel</small>)</tt> ";
 195+ / We don't currently handle well changing the top revision's settings
 196+ if( $this->mNewRev->isCurrent() ) {
 197+ / If revision was hidden from sysops
 198+ $rdel = wfMsgHtml('rev-delundel');
 199+ } else if( !$this->mNewRev->userCan( Revision::DELETED_RESTRICTED ) ) {
 200+ / If revision was hidden from sysops
 201+ $rdel = wfMsgHtml('rev-delundel');
 202+ } else {
 203+ $rdel = $sk->makeKnownLinkObj( $revdel,
 204+ wfMsgHtml('rev-delundel'),
 205+ 'target=' . urlencode( $this->mNewRev->mTitle->getPrefixedDbkey() ) .
 206+ '&oldid=' . urlencode( $this->mNewRev->getId() ) );
 207+ / Bolden oversighted content
 208+ if( $this->mNewRev->isDeleted( Revision::DELETED_RESTRICTED ) )
 209+ $rdel = "<strong>$rdel</strong>";
 210+ }
 211+ $rdel = "&nbsp;&nbsp;&nbsp;<tt>(<small>$rdel</small>)</tt> ";
 212+ }
178213
179214 $oldHeader = "<strong>{$this->mOldtitle}</strong><br />" .
180 - $sk->revUserTools( $this->mOldRev ) . "<br />" .
181 - $oldminor . $sk->revComment( $this->mOldRev, !$diffOnly ) . "<br />" .
 215+ $sk->revUserTools( $this->mOldRev, true ) . "<br />" .
 216+ $oldminor . $sk->revComment( $this->mOldRev, !$diffOnly, true ) . "$ldel<br />" .
182217 $prevlink;
183218 $newHeader = "<strong>{$this->mNewtitle}</strong><br />" .
184 - $sk->revUserTools( $this->mNewRev ) . " $rollback<br />" .
185 - $newminor . $sk->revComment( $this->mNewRev, !$diffOnly ) . "<br />" .
 219+ $sk->revUserTools( $this->mNewRev, true ) . " $rollback<br />" .
 220+ $newminor . $sk->revComment( $this->mNewRev, !$diffOnly, true ) . "$rdel<br />" .
186221 $nextlink . $patrol;
187222
188223 $this->showDiff( $oldHeader, $newHeader );
@@ -202,8 +237,10 @@
203238
204239 $wgOut->addHTML( "<hr /><h2>{$this->mPagetitle}</h2>\n" );
205240 #add deleted rev tag if needed
206 - if ( !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) {
 241+ if( !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) {
207242 $wgOut->addWikiText( wfMsg( 'rev-deleted-text-permission' ) );
 243+ } else if( $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) {
 244+ $wgOut->addWikiText( wfMsg( 'rev-deleted-text-view' ) );
208245 }
209246
210247 if( !$this->mNewRev->isCurrent() ) {
@@ -332,20 +369,25 @@
333370 }
334371 }
335372
336 - #loadtext is permission safe, this just clears out the diff
 373+ / Loadtext is permission safe, this just clears out the diff
337374 if ( !$this->loadText() ) {
338375 wfProfileOut( $fname );
339376 return false;
340377 } else if ( $this->mOldRev && !$this->mOldRev->userCan(Revision::DELETED_TEXT) ) {
341 - return '';
 378+ return '';
342379 } else if ( $this->mNewRev && !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) {
343 - return '';
 380+ return '';
344381 }
345382
346383 $difftext = $this->generateDiffBody( $this->mOldtext, $this->mNewtext );
347384
348385 / Save to cache for 7 days
349 - if ( $key !== false && $difftext !== false ) {
 386+ / Only do this for public revs, otherwise an admin can view the diff and a non-admin can nab it!
 387+ if ( $this->mOldRev && $this->mOldRev->isDeleted(Revision::DELETED_TEXT) ) {
 388+ wfIncrStats( 'diff_uncacheable' );
 389+ } else if ( $this->mNewRev && $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) {
 390+ wfIncrStats( 'diff_uncacheable' );
 391+ } else if ( $key !== false && $difftext !== false ) {
350392 wfIncrStats( 'diff_cache_miss' );
351393 $wgMemc->set( $key, $difftext, 7*86400 );
352394 } else {
@@ -479,13 +521,7 @@
480522 */
481523 function addHeader( $diff, $otitle, $ntitle, $multi = '' ) {
482524 global $wgOut;
483 -
484 - if ( $this->mOldRev && $this->mOldRev->isDeleted(Revision::DELETED_TEXT) ) {
485 - $otitle = '<span class="history-deleted">'.$otitle.'</span>';
486 - }
487 - if ( $this->mNewRev && $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) {
488 - $ntitle = '<span class="history-deleted">'.$ntitle.'</span>';
489 - }
 525+
490526 $header = "
491527 <table border='0' width='98%' cellpadding='0' cellspacing='4' class='diff'>
492528 <tr>
@@ -558,6 +594,11 @@
559595 $this->mNewtitle = "<a href='$newLink'>{$this->mPagetitle}</a>"
560596 . " (<a href='$newEdit'>" . htmlspecialchars( wfMsg( 'editold' ) ) . "</a>)";
561597 }
 598+ if ( !$this->mNewRev->userCan(Revision::DELETED_TEXT) ) {
 599+ $this->mNewtitle = "<span class='history-deleted'>{$this->mPagetitle}</span>";
 600+ } else if ( $this->mNewRev->isDeleted(Revision::DELETED_TEXT) ) {
 601+ $this->mNewtitle = '<span class="history-deleted">'.$this->mNewtitle.'</span>';
 602+ }
562603
563604 / Load the old revision object
564605 $this->mOldRev = false;
@@ -585,11 +626,20 @@
586627 $t = $wgLang->timeanddate( $this->mOldRev->getTimestamp(), true );
587628 $oldLink = $this->mOldPage->escapeLocalUrl( 'oldid=' . $this->mOldid );
588629 $oldEdit = $this->mOldPage->escapeLocalUrl( 'action=edit&oldid=' . $this->mOldid );
589 - $this->mOldtitle = "<a href='$oldLink'>" . htmlspecialchars( wfMsg( 'revisionasof', $t ) )
590 - . "</a> (<a href='$oldEdit'>" . htmlspecialchars( wfMsg( 'editold' ) ) . "</a>)";
591 - /now that we considered old rev, we can make undo link (bug 8133, multi-edit undo)
 630+ $this->mOldPagetitle = htmlspecialchars( wfMsg( 'revisionasof', $t ) );
 631+
 632+ $this->mOldtitle = "<a href='$oldLink'>{$this->mOldPagetitle}</a>"
 633+ . "(<a href='$oldEdit'>" . htmlspecialchars( wfMsg( 'editold' ) ) . "</a>)";
 634+ / Now that we considered old rev, we can make undo link (bug 8133, multi-edit undo)
592635 $newUndo = $this->mNewPage->escapeLocalUrl( 'action=edit&undoafter=' . $this->mOldid . '&undoto=' . $this->mNewid);
593 - $this->mNewtitle .= " (<a href='$newUndo'>" . htmlspecialchars( wfMsg( 'editundo' ) ) . "</a>)";
 636+ if ( $this->mNewRev->userCan(Revision::DELETED_TEXT) )
 637+ $this->mNewtitle .= " (<a href='$newUndo'>" . htmlspecialchars( wfMsg( 'editundo' ) ) . "</a>)";
 638+
 639+ if ( !$this->mOldRev->userCan(Revision::DELETED_TEXT) ) {
 640+ $this->mOldtitle = "<span class='history-deleted'>{$this->mOldPagetitle}</span>";
 641+ } else if ( $this->mOldRev->isDeleted(Revision::DELETED_TEXT) ) {
 642+ $this->mOldtitle = '<span class="history-deleted">'.$this->mOldtitle.'</span>';
 643+ }
594644 }
595645
596646 return true;
@@ -610,7 +660,6 @@
611661 return false;
612662 }
613663 if ( $this->mOldRev ) {
614 - / FIXME: permission tests
615664 $this->mOldtext = $this->mOldRev->revText();
616665 if ( $this->mOldtext === false ) {
617666 return false;
Index: trunk/phase3/includes/SpecialLog.php
@@ -72,16 +72,70 @@
7373
7474 list( $this->limit, $this->offset ) = $request->getLimitOffset();
7575 }
 76+
 77+ function newFromTitle( $title, $logid=0 ) {
 78+ $fname = 'LogReader::newFromTitle';
7679
 80+ $matchId = intval( $logid );
 81+ $dbr = wfGetDB( DB_SLAVE );
 82+ $res = $dbr->select( 'logging', array('*'),
 83+ array('log_id' => $matchId, 'log_namespace' => $title->getNamespace(), 'log_title' => $title->getDBkey() ),
 84+ $fname );
 85+
 86+ if ( $res ) {
 87+ $ret = $dbr->fetchObject( $res );
 88+ if ( $ret ) {
 89+ return $ret;
 90+ }
 91+ }
 92+ return null;
 93+ }
 94+
 95+ function newFromId( $logid ) {
 96+ $fname = 'LogReader::newFromId';
 97+
 98+ $matchId = intval( $logid );
 99+ $dbr = wfGetDB( DB_SLAVE );
 100+ $res = $dbr->select( 'logging', array('*'), array('log_id' => $matchId ), $fname );
 101+
 102+ if ( $res ) {
 103+ $ret = $dbr->fetchObject( $res );
 104+ if ( $ret ) {
 105+ return $ret;
 106+ }
 107+ }
 108+ return null;
 109+ }
 110+
77111 /**
78112 * Set the log reader to return only entries of the given type.
 113+ * Type restrictions enforced here
79114 * @param string $type A log type ('upload', 'delete', etc)
80115 * @private
81116 */
82117 function limitType( $type ) {
 118+ global $wgLogRestrictions, $wgUser;
 119+
 120+ / Restriction system
 121+ if ( isset($wgLogRestrictions) ) {
 122+ foreach ( $wgLogRestrictions as $logtype => $right ) {
 123+ if ( !$wgUser->isAllowed( $right ) ) {
 124+ $safetype = $this->db->strencode( $logtype );
 125+ $this->whereClauses[] = "log_type <> '$safetype'";
 126+ }
 127+ }
 128+ }
 129+
83130 if( empty( $type ) ) {
84131 return false;
85132 }
 133+ / Can user see this log?
 134+ if ( isset($wgLogRestrictions[$type]) ) {
 135+ if ( !$wgUser->isAllowed( $wgLogRestrictions[$type] ) ) {
 136+ return false;
 137+ }
 138+ }
 139+
86140 $this->type = $type;
87141 $safetype = $this->db->strencode( $type );
88142 $this->whereClauses[] = "log_type='$safetype'";
@@ -117,7 +171,7 @@
118172 * @private
119173 */
120174 function limitTitle( $page , $pattern ) {
121 - $title = Title::newFromText( $page );
 175+ $title = Title::newFromURL( $page, false );
122176 if( empty( $page ) || is_null( $title ) ) {
123177 return false;
124178 }
@@ -157,6 +211,7 @@
158212 $logging = $this->db->tableName( "logging" );
159213 $sql = "SELECT /*! STRAIGHT_JOIN */ log_type, log_action, log_timestamp,
160214 log_user, user_name,
 215+ log_id, log_deleted,
161216 log_namespace, log_title, page_id,
162217 log_comment, log_params FROM $logging ";
163218 if( !empty( $this->joinClauses ) ) {
@@ -217,6 +272,11 @@
218273 * @addtogroup SpecialPage
219274 */
220275 class LogViewer {
 276+ const DELETED_ACTION = 1;
 277+ const DELETED_COMMENT = 2;
 278+ const DELETED_USER = 4;
 279+ const DELETED_RESTRICTED = 8;
 280+
221281 /**
222282 * @var LogReader $reader
223283 */
@@ -230,7 +290,21 @@
231291 global $wgUser;
232292 $this->skin = $wgUser->getSkin();
233293 $this->reader =& $reader;
 294+ $this->preCacheMessages();
234295 }
 296+
 297+ /**
 298+ * As we use the same small set of messages in various methods and that
 299+ * they are called often, we call them once and save them in $this->message
 300+ */
 301+ function preCacheMessages() {
 302+ / Precache various messages
 303+ if( !isset( $this->message ) ) {
 304+ foreach( explode(' ', 'viewpagelogs revhistory imghistory rev-delundel' ) as $msg ) {
 305+ $this->message[$msg] = wfMsgExt( $msg, array( 'escape') );
 306+ }
 307+ }
 308+ }
235309
236310 /**
237311 * Take over the whole output page in $wgOut with the log display.
@@ -248,8 +322,125 @@
249323 $this->showError( $wgOut );
250324 }
251325 }
 326+
 327+ /**
 328+ * Determine if the current user is allowed to view a particular
 329+ * field of this event, if it's marked as deleted.
 330+ * @param int $field
 331+ * @return bool
 332+ */
 333+ function userCan( $event, $field ) {
 334+ if( ( $event->log_deleted & $field ) == $field ) {
 335+ global $wgUser;
 336+ $permission = ( $event->log_deleted & Revision::DELETED_RESTRICTED ) == Revision::DELETED_RESTRICTED
 337+ ? 'hiderevision'
 338+ : 'deleterevision';
 339+ wfDebug( "Checking for $permission due to $field match on $event->log_deleted\n" );
 340+ return $wgUser->isAllowed( $permission );
 341+ } else {
 342+ return true;
 343+ }
 344+ }
 345+
 346+ /**
 347+ * int $field one of DELETED_* bitfield constants
 348+ * @return bool
 349+ */
 350+ function isDeleted( $event, $field ) {
 351+ return ($event->log_deleted & $field) == $field;
 352+ }
 353+
 354+ /**
 355+ * Fetch event's user id if it's available to all users
 356+ * @return int
 357+ */
 358+ function getUser( $event ) {
 359+ if( $this->isDeleted( $event, Revision::DELETED_USER ) ) {
 360+ return 0;
 361+ } else {
 362+ return $event->log_user;
 363+ }
 364+ }
252365
253366 /**
 367+ * Fetch event's user id without regard for the current user's permissions
 368+ * @return string
 369+ */
 370+ function getRawUser( $event ) {
 371+ return $event->log_user;
 372+ }
 373+
 374+ /**
 375+ * Fetch event's username if it's available to all users
 376+ * @return string
 377+ */
 378+ function getUserText( $event ) {
 379+ if( $this->isDeleted( $event, Revision::DELETED_USER ) ) {
 380+ return "";
 381+ } else {
 382+ if ( isset($event->user_name) ) {
 383+ return $event->user_name;
 384+ } else {
 385+ return User::whoIs( $event->log_user );
 386+ }
 387+ }
 388+ }
 389+
 390+ /**
 391+ * Fetch event's username without regard for view restrictions
 392+ * @return string
 393+ */
 394+ function getRawUserText( $event ) {
 395+ if ( isset($event->user_name) ) {
 396+ return $event->user_name;
 397+ } else {
 398+ return User::whoIs( $event->log_user );
 399+ }
 400+ }
 401+
 402+ /**
 403+ * Fetch event comment if it's available to all users
 404+ * @return string
 405+ */
 406+ function getComment( $event ) {
 407+ if( $this->isDeleted( $event, Revision::DELETED_COMMENT ) ) {
 408+ return "";
 409+ } else {
 410+ return $event->log_comment;
 411+ }
 412+ }
 413+
 414+ /**
 415+ * Fetch event comment without regard for the current user's permissions
 416+ * @return string
 417+ */
 418+ function getRawComment( $event ) {
 419+ return $event->log_comment;
 420+ }
 421+
 422+ /**
 423+ * Returns the title of the page associated with this entry.
 424+ * @return Title
 425+ */
 426+ function getTitle( $event ) {
 427+ return Title::makeTitle( $event->log_namespace, $event->log_title );
 428+ }
 429+
 430+ /**
 431+ * Return the log action if it's available to all users
 432+ * default is deleted if not specified for security
 433+ * @return Title
 434+ */
 435+ function logActionText( $log_type, $log_action, $title, $skin, $paramArray, $log_deleted = LogViewer::DELETED_ACTION ) {
 436+ if( $log_deleted & LogViewer::DELETED_ACTION ) {
 437+ return '<span class="history-deleted">' . wfMsgHtml('rev-deleted-event') . '</span>';
 438+ } else {
 439+ $action = LogPage::actionText( $log_type, $log_action, $title, $this->skin, $paramArray, true, true );
 440+ return $action;
 441+ }
 442+ }
 443+
 444+ /**
254445 * Load the data from the linked LogReader
255446 * Preload the link cache
256447 * Initialise numResults
@@ -319,7 +510,8 @@
320511 * @private
321512 */
322513 function logLine( $s ) {
323 - global $wgLang, $wgUser;;
 514+ global $wgLang, $wgUser;
 515+
324516 $skin = $wgUser->getSkin();
325517 $title = Title::makeTitle( $s->log_namespace, $s->log_title );
326518 $time = $wgLang->timeanddate( wfTimestamp(TS_MW, $s->log_timestamp), true );
@@ -332,12 +524,64 @@
333525 } else {
334526 $linkCache->addBadLinkObj( $title );
335527 }
 528+ / User links
 529+ $userLink = $this->skin->logUserTools( $s, true );
 530+ / Comment
 531+ $comment = $this->skin->logComment( $s, true );
336532
337 - $userLink = $this->skin->userLink( $s->log_user, $s->user_name ) . $this->skin->userToolLinksRedContribs( $s->log_user, $s->user_name );
338 - $comment = $this->skin->commentBlock( $s->log_comment );
339533 $paramArray = LogPage::extractParams( $s->log_params );
340 - $revert = '';
341 - / show revertmove link
 534+ $revert = ''; $del = '';
 535+
 536+ / Some user can hide log items and have review links
 537+ if( $wgUser->isAllowed( 'deleterevision' ) ) {
 538+ $del = $this->showhideLinks( $s, $title );
 539+ }
 540+
 541+ / Show restore/unprotect/unblock
 542+ $revert = $this->showReviewLinks( $s, $title, $paramArray );
 543+
 544+ / Event description
 545+ $action = $this->logActionText( $s->log_type, $s->log_action, $title, $this->skin, $paramArray, $s->log_deleted );
 546+
 547+ $out = "<li><tt>$del</tt> $time $userLink $action $comment <small>$revert</small></li>\n";
 548+ return $out;
 549+ }
 550+
 551+ /**
 552+ * @param $s, row object
 553+ * @param $s, title object
 554+ * @private
 555+ */
 556+ function showhideLinks( $s, $title ) {
 557+ $revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
 558+ if( !LogViewer::userCan( $s, Revision::DELETED_RESTRICTED ) ) {
 559+ / If event was hidden from sysops
 560+ $del = $this->message['rev-delundel'];
 561+ } else if( $s->log_type == 'oversight' ) {
 562+ / No one should be hiding from the oversight log
 563+ $del = $this->message['rev-delundel'];
 564+ } else {
 565+ $del = $this->skin->makeKnownLinkObj( $revdel,
 566+ $this->message['rev-delundel'],
 567+ 'target=' . urlencode( $title->getPrefixedDbkey() ) . '&logid=' . $s->log_id );
 568+ / Bolden oversighted content
 569+ if( LogViewer::isDeleted( $s, Revision::DELETED_RESTRICTED ) )
 570+ $del = "<strong>$del</strong>";
 571+ }
 572+ return "(<small>$del</small>)";
 573+ }
 574+
 575+ /**
 576+ * @param $s, row object
 577+ * @param $title, title object
 578+ * @param $s, param array
 579+ * @private
 580+ */
 581+ function showReviewLinks( $s, $title, $paramArray ) {
 582+ global $wgUser;
 583+
 584+ $reviewlink='';
 585+ / Show revertmove link
342586 if ( $s->log_type == 'move' && isset( $paramArray[0] ) ) {
343587 $destTitle = Title::newFromText( $paramArray[0] );
344588 if ( $destTitle ) {
@@ -349,26 +593,47 @@
350594 '&wpMovetalk=0' ) . ')';
351595 }
352596 / show undelete link
353 - } elseif ( $s->log_action == 'delete' && $wgUser->isAllowed( 'delete' ) ) {
354 - $revert = '(' . $this->skin->makeKnownLinkObj( SpecialPage::getTitleFor( 'Undelete' ),
 597+ } else if ( $s->log_action == 'delete' && $wgUser->isAllowed( 'delete' ) ) {
 598+ $reviewlink = $this->skin->makeKnownLinkObj( SpecialPage::getTitleFor( 'Undelete' ),
355599 wfMsg( 'undeletebtn' ) ,
356 - 'target='. urlencode( $title->getPrefixedDBkey() ) ) . ')';
357 -
 600+ 'target='. urlencode( $title->getPrefixedDBkey() ) );
358601 / show unblock link
359602 } elseif ( $s->log_action == 'block' && $wgUser->isAllowed( 'block' ) ) {
360 - $revert = '(' . $skin->makeKnownLinkObj( SpecialPage::getTitleFor( 'Ipblocklist' ),
 603+ $reviewlink = $this->skin->makeKnownLinkObj( SpecialPage::getTitleFor( 'Ipblocklist' ),
361604 wfMsg( 'unblocklink' ),
362 - 'action=unblock&ip=' . urlencode( $s->log_title ) ) . ')';
 605+ 'action=unblock&ip=' . urlencode( $s->log_title ) );
363606 / show change protection link
364607 } elseif ( $s->log_action == 'protect' && $wgUser->isAllowed( 'protect' ) ) {
365 - $revert = '(' . $skin->makeKnownLink( $title->getPrefixedDBkey() ,
 608+ $reviewlink = $this->skin->makeKnownLink( $title->getPrefixedDBkey() ,
366609 wfMsg( 'protect_change' ),
367 - 'action=unprotect' ) . ')';
 610+ 'action=unprotect' );
368611 }
369 -
370 - $action = LogPage::actionText( $s->log_type, $s->log_action, $title, $this->skin, $paramArray, true, true );
371 - $out = "<li>$time $userLink $action $comment $revert</li>\n";
372 - return $out;
 612+ / If an edit was hidden from a page give a review link to the history
 613+ if ( $wgUser->isAllowed( 'deleterevision' ) && isset($paramArray[2]) ) {
 614+ $revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
 615+ if ( $s->log_action == 'revision' ) {
 616+ $reviewlink = $this->skin->makeKnownLinkObj( $title, $this->message['revhistory'],
 617+ wfArrayToCGI( array('action' => 'history' ) ) ) . ':';
 618+ } else if ( $s->log_action == 'file' ) {
 619+ / Currently, only deleted file versions can be hidden
 620+ $undelete = SpecialPage::getTitleFor( 'Undelete' );
 621+ $reviewlink = $this->skin->makeKnownLinkObj( $undelete, $this->message['imghistory'],
 622+ wfArrayToCGI( array('target' => $title->getPrefixedText() ) ) ) . ':';
 623+ } else if ( $s->log_action == 'event' && isset($paramArray[0]) ) {
 624+ / If this event was to a log, give a review link to logs for that page only
 625+ $reviewlink = $this->skin->makeKnownLinkObj( $title, $this->message['viewpagelogs'],
 626+ wfArrayToCGI( array('page' => $paramArray[0] ) ) ) . ':';
 627+ }
 628+ / Link to each hidden object ID
 629+ $IdType = $paramArray[1].'id';
 630+ $Ids = explode( ',', $paramArray[2] );
 631+ foreach ( $Ids as $id ) {
 632+ $reviewlink .= ' '.$this->skin->makeKnownLinkObj( $revdel, "#$id",
 633+ wfArrayToCGI( array('target' => $paramArray[0], $IdType => $id ) ) );
 634+ }
 635+ }
 636+ $reviewlink = ( $reviewlink=='' ) ? "" : "&nbsp;&nbsp;&nbsp;($reviewlink) ";
 637+ return $reviewlink;
373638 }
374639
375640 /**
@@ -409,6 +674,8 @@
410675 * @private
411676 */
412677 function getTypeMenu() {
 678+ global $wgLogRestrictions, $wgUser;
 679+
413680 $out = "<select name='type'>\n";
414681
415682 $validTypes = LogPage::validTypes();
@@ -426,7 +693,14 @@
427694 / Third pass generates sorted XHTML content
428695 foreach( $m as $text => $type ) {
429696 $selected = ($type == $this->reader->queryType());
 697+ / Restricted types
 698+ if ( isset($wgLogRestrictions[$type]) ) {
 699+ if ( $wgUser->isAllowed( $wgLogRestrictions[$type] ) ) {
 700+ $out .= Xml::option( $text, $type, $selected ) . "\n";
 701+ }
 702+ } else {
430703 $out .= Xml::option( $text, $type, $selected ) . "\n";
 704+ }
431705 }
432706
433707 $out .= '</select>';
@@ -484,5 +758,12 @@
485759 }
486760 }
487761
 762+/**
 763+ * Aliases for backwards compatibility with 1.6
 764+ */
 765+define( 'MW_LOG_DELETED_ACTION', LogViewer::DELETED_ACTION );
 766+define( 'MW_LOG_DELETED_USER', LogViewer::DELETED_USER );
 767+define( 'MW_LOG_DELETED_COMMENT', LogViewer::DELETED_COMMENT );
 768+define( 'MW_LOG_DELETED_RESTRICTED', LogViewer::DELETED_RESTRICTED );
488769
489770 ?>
Index: trunk/phase3/includes/DefaultSettings.php
@@ -169,7 +169,7 @@
170170 * is writable to the web server but is not exposed to the internet.
171171 *
172172 * Set $wgSaveDeletedFiles to true and set up the save path in
173 - * $wgFileStore['deleted']['directory'].
 173+ * $wgFileStore['deleted']['directory']
174174 */
175175 $wgSaveDeletedFiles = false;
176176
@@ -983,6 +983,7 @@
984984 $wgGroupPermissions['sysop']['block'] = true;
985985 $wgGroupPermissions['sysop']['createaccount'] = true;
986986 $wgGroupPermissions['sysop']['delete'] = true;
 987+$wgGroupPermissions['sysop']['browsearchive'] = true; / can see the deleted page list
987988 $wgGroupPermissions['sysop']['deletedhistory'] = true; / can view deleted history entries, but not see or restore the text
988989 $wgGroupPermissions['sysop']['editinterface'] = true;
989990 $wgGroupPermissions['sysop']['import'] = true;
@@ -1005,9 +1006,17 @@
10061007 / Permission to change users' group assignments
10071008 $wgGroupPermissions['bureaucrat']['userrights'] = true;
10081009
1009 -/ Experimental permissions, not ready for production use
 1010+/ Experimental permissions to enable revisiondelete:
 1011+
10101012 /$wgGroupPermissions['sysop']['deleterevision'] = true;
 1013+/$wgGroupPermissions['sysop']['hideuser'] = true;
 1014+/ To see hidden revs
10111015 /$wgGroupPermissions['bureaucrat']['hiderevision'] = true;
 1016+/ For private log access
 1017+/$wgGroupPermissions['bureaucrat']['oversight'] = true;
 1018+/ Also, we may want titles to be effectively hidden
 1019+/$wgGroupPermissions['sysop']['browsearchive'] = false;
 1020+/$wgGroupPermissions['bureaucrat']['browsearchive'] = true;
10121021
10131022 /**
10141023 * The developer group is deprecated, but can be activated if need be
@@ -2023,9 +2032,20 @@
20242033 'move',
20252034 'import',
20262035 'patrol',
 2036+ 'oversight',
20272037 );
20282038
20292039 /**
 2040+ * This restricts log access to those who have a certain right
 2041+ * Users without this will not see it in the option menu and can not view it
 2042+ * Restricted logs are not added to recent changes
 2043+ * Logs should remain non-transcludable
 2044+ */
 2045+$wgLogRestrictions = array(
 2046+'oversight' => 'oversight'
 2047+);
 2048+
 2049+/**
20302050 * Lists the message key string for each log type. The localized messages
20312051 * will be listed in the user interface.
20322052 *
@@ -2041,6 +2061,7 @@
20422062 'move' => 'movelogpage',
20432063 'import' => 'importlogpage',
20442064 'patrol' => 'patrol-log-page',
 2065+ 'oversight' => 'oversightlog',
20452066 );
20462067
20472068 /**
@@ -2059,6 +2080,7 @@
20602081 'move' => 'movelogpagetext',
20612082 'import' => 'importlogpagetext',
20622083 'patrol' => 'patrol-log-header',
 2084+ 'oversight' => 'overlogpagetext',
20632085 );
20642086
20652087 /**
@@ -2076,12 +2098,18 @@
20772099 'delete/delete' => 'deletedarticle',
20782100 'delete/restore' => 'undeletedarticle',
20792101 'delete/revision' => 'revdelete-logentry',
 2102+ 'delete/event' => 'logdelete-logentry',
20802103 'upload/upload' => 'uploadedimage',
20812104 'upload/revert' => 'uploadedimage',
20822105 'move/move' => '1movedto2',
20832106 'move/move_redir' => '1movedto2_redir',
20842107 'import/upload' => 'import-logentry-upload',
20852108 'import/interwiki' => 'import-logentry-interwiki',
 2109+ 'oversight/revision' => 'revdelete-logentry',
 2110+ 'oversight/file' => 'revdelete-logentry',
 2111+ 'oversight/event' => 'logdelete-logentry',
 2112+ 'oversight/delete' => 'deletedarticle',
 2113+ 'oversight/block' => 'blocklogentry',
20862114 );
20872115
20882116 /**
Index: trunk/phase3/includes/PageHistory.php
@@ -38,7 +38,21 @@
3939 $this->mTitle =& $article->mTitle;
4040 $this->mNotificationTimestamp = NULL;
4141 $this->mSkin = $wgUser->getSkin();
 42+ $this->preCacheMessages();
4243 }
 44+
 45+ /**
 46+ * As we use the same small set of messages in various methods and that
 47+ * they are called often, we call them once and save them in $this->message
 48+ */
 49+ function preCacheMessages() {
 50+ / Precache various messages
 51+ if( !isset( $this->message ) ) {
 52+ foreach( explode(' ', 'cur last rev-delundel' ) as $msg ) {
 53+ $this->message[$msg] = wfMsgExt( $msg, array( 'escape') );
 54+ }
 55+ }
 56+ }
4357
4458 /**
4559 * Print the history page for an article.
@@ -187,35 +201,31 @@
188202 $arbitrary = $this->diffButtons( $rev, $firstInList, $counter );
189203 $link = $this->revLink( $rev );
190204
191 - $user = $this->mSkin->userLink( $rev->getUser(), $rev->getUserText() )
192 - . $this->mSkin->userToolLinks( $rev->getUser(), $rev->getUserText() );
193 -
194205 $s .= "($curlink) ($lastlink) $arbitrary";
195206
196207 if( $wgUser->isAllowed( 'deleterevision' ) ) {
197208 $revdel = SpecialPage::getTitleFor( 'Revisiondelete' );
198209 if( $firstInList ) {
199 - / We don't currently handle well changing the top revision's settings
200 - $del = wfMsgHtml( 'rev-delundel' );
 210+ / We don't currently handle well changing the top revision's settings
 211+ $del = $this->message['rev-delundel'];
201212 } else if( !$rev->userCan( Revision::DELETED_RESTRICTED ) ) {
202213 / If revision was hidden from sysops
203 - $del = wfMsgHtml( 'rev-delundel' );
 214+ $del = $this->message['rev-delundel'];
204215 } else {
205216 $del = $this->mSkin->makeKnownLinkObj( $revdel,
206 - wfMsg( 'rev-delundel' ),
 217+ $this->message['rev-delundel'],
207218 'target=' . urlencode( $this->mTitle->getPrefixedDbkey() ) .
208219 '&oldid=' . urlencode( $rev->getId() ) );
 220+ / Bolden oversighted content
 221+ if( $rev->isDeleted( Revision::DELETED_RESTRICTED ) )
 222+ $del = "<strong>$del</strong>";
209223 }
210 - $s .= " (<small>$del</small>) ";
 224+ $s .= " <tt>(<small>$del</small>)</tt> ";
211225 }
212226
213227 $s .= " $link";
214 - #getUser is safe, but this avoids making the invalid untargeted contribs links
215 - if( $row->rev_deleted & Revision::DELETED_USER ) {
216 - $user = '<span class="history-deleted">' . wfMsg('rev-deleted-user') . '</span>';
217 - }
218 - $s .= " <span class='history-user'>$user</span>";
219 -
 228+ $s .= $this->mSkin->revUserTools( $rev, true);
 229+
220230 if( $row->rev_minor_edit ) {
221231 $s .= ' ' . wfElement( 'span', array( 'class' => 'minor' ), wfMsg( 'minoreditletter') );
222232 }
@@ -241,7 +251,7 @@
242252 }
243253 #add blurb about text having been deleted
244254 if( $row->rev_deleted & Revision::DELETED_TEXT ) {
245 - $s .= ' ' . wfMsgHtml( 'deletedrev' );
 255+ $s .= ' <tt>' . wfMsgHtml( 'deletedrev' ) . '</tt>';
246256 }
247257 if( $wgUser->isAllowed( 'rollback' ) && $latest ) {
248258 $s .= ' '.$this->mSkin->generateRollback( $rev );
@@ -269,7 +279,7 @@
270280
271281 /** @todo document */
272282 function curLink( $rev, $latest ) {
273 - $cur = wfMsgExt( 'cur', array( 'escape') );
 283+ $cur = $this->message['cur'];
274284 if( $latest || !$rev->userCan( Revision::DELETED_TEXT ) ) {
275285 return $cur;
276286 } else {
@@ -282,7 +292,7 @@
283293
284294 /** @todo document */
285295 function lastLink( $rev, $next, $counter ) {
286 - $last = wfMsgExt( 'last', array( 'escape' ) );
 296+ $last = $this->message['last'];
287297 if ( is_null( $next ) ) {
288298 # Probably no next row
289299 return $last;
Index: trunk/phase3/includes/LogPage.php
@@ -50,13 +50,15 @@
5151 function saveContent() {
5252 if( wfReadOnly() ) return false;
5353
54 - global $wgUser;
 54+ global $wgUser, $wgLogRestrictions;
5555 $fname = 'LogPage::saveContent';
5656
5757 $dbw = wfGetDB( DB_MASTER );
5858 $uid = $wgUser->getID();
5959
6060 $this->timestamp = $now = wfTimestampNow();
 61+
 62+ $log_id = $dbw->nextSequenceValue( 'log_log_id_seq' );
6163 $dbw->insert( 'logging',
6264 array(
6365 'log_type' => $this->type,
@@ -69,20 +71,15 @@
7072 'log_params' => $this->params
7173 ), $fname
7274 );
 75+ $newId = $dbw->insertId();
7376
7477 # And update recentchanges
7578 if ( $this->updateRecentChanges ) {
76 - $titleObj = SpecialPage::getTitleFor( 'Log', $this->type );
77 - $rcComment = $this->actionText;
78 - if( '' != $this->comment ) {
79 - if ($rcComment == '')
80 - $rcComment = $this->comment;
81 - else
82 - $rcComment .= ': ' . $this->comment;
 79+ # Don't add private logs to RC!!!
 80+ if ( !isset($wgLogRestrictions[$this->type]) || $wgLogRestrictions[$this->type]=='*' ) {
 81+ RecentChange::notifyLog( $now, $this->target, $wgUser, $this->actionText, '',
 82+ $this->type, $this->action, $this->target, $this->comment, $this->params, $newId );
8383 }
84 -
85 - RecentChange::notifyLog( $now, $titleObj, $wgUser, $rcComment, '',
86 - $this->type, $this->action, $this->target, $this->comment, $this->params );
8784 }
8885 return true;
8986 }
@@ -122,13 +119,13 @@
123120 */
124121 function logHeader( $type ) {
125122 global $wgLogHeaders;
126 - return wfMsg( $wgLogHeaders[$type] );
 123+ return wfMsgHtml( $wgLogHeaders[$type] );
127124 }
128125
129126 /**
130127 * @static
131128 */
132 - function actionText( $type, $action, $title = NULL, $skin = NULL, $params = array(), $filterWikilinks=false, $translate=false ) {
 129+ function actionText( $type, $action, $title=NULL, $skin=NULL, $params = array(), $filterWikilinks=false, $translate=false, $forRC=false ) {
133130 global $wgLang, $wgContLang, $wgLogActions;
134131
135132 $key = "$type/$action";
@@ -185,12 +182,17 @@
186183 }
187184 } else {
188185 array_unshift( $params, $titleLink );
189 - if ( $translate && $key == 'block/block' ) {
 186+ / Oversighted blocks show as normal
 187+ if ( $translate && ($key == 'block/block' || $key == 'oversight/block') ) {
190188 $params[1] = $wgLang->translateBlockExpiry( $params[1] );
191189 $params[2] = isset( $params[2] )
192190 ? self::formatBlockFlags( $params[2] )
193191 : '';
194192 }
 193+ if ( $forRC ) {
 194+ $params[1] = $wgLang->translateBlockExpiry( $params[1], true );
 195+ $params[2] = isset( $params[2] ) ? str_replace( ",", ", ", self::formatBlockFlags( $params[2] ) ) : '';
 196+ }
195197 $rv = wfMsgReal( $wgLogActions[$key], $params, true, !$skin );
196198 }
197199 }
@@ -222,7 +224,7 @@
223225 $this->comment = $comment;
224226 $this->params = LogPage::makeParamBlob( $params );
225227
226 - $this->actionText = LogPage::actionText( $this->type, $action, $target, NULL, $params );
 228+ $this->actionText = LogPage::actionText( $this->type, $action, $target, NULL, $params, false, false, true );
227229
228230 return $this->saveContent();
229231 }

Follow-up revisions

RevisionCommit summaryAuthorDate
r20506* Update German translations and messages.inc...raymond08:03, 16 March 2007
r20570Reverting SpecialRevisiondelete.php back to r17880, to fix nickj07:41, 21 March 2007

Follow Lee on X/Twitter - Father, Husband, Serial builder creating AI, crypto, games & web tools. We are friends :) AI Will Come To Life!

Check out: eBank.nz (Art Generator) | Netwrck.com (AI Tools) | Text-Generator.io (AI API) | BitBank.nz (Crypto AI) | ReadingTime (Kids Reading) | RewordGame | BigMultiplayerChess | WebFiddle | How.nz | Helix AI Assistant