MediaWiki
REL1_24
|
00001 <?php 00028 class DeletedContribsPager extends IndexPager { 00029 public $mDefaultDirection = IndexPager::DIR_DESCENDING; 00030 public $messages; 00031 public $target; 00032 public $namespace = ''; 00033 public $mDb; 00034 00038 protected $mNavigationBar; 00039 00040 function __construct( IContextSource $context, $target, $namespace = false ) { 00041 parent::__construct( $context ); 00042 $msgs = array( 'deletionlog', 'undeleteviewlink', 'diff' ); 00043 foreach ( $msgs as $msg ) { 00044 $this->messages[$msg] = $this->msg( $msg )->escaped(); 00045 } 00046 $this->target = $target; 00047 $this->namespace = $namespace; 00048 $this->mDb = wfGetDB( DB_SLAVE, 'contributions' ); 00049 } 00050 00051 function getDefaultQuery() { 00052 $query = parent::getDefaultQuery(); 00053 $query['target'] = $this->target; 00054 00055 return $query; 00056 } 00057 00058 function getQueryInfo() { 00059 list( $index, $userCond ) = $this->getUserCond(); 00060 $conds = array_merge( $userCond, $this->getNamespaceCond() ); 00061 $user = $this->getUser(); 00062 // Paranoia: avoid brute force searches (bug 17792) 00063 if ( !$user->isAllowed( 'deletedhistory' ) ) { 00064 $conds[] = $this->mDb->bitAnd( 'ar_deleted', Revision::DELETED_USER ) . ' = 0'; 00065 } elseif ( !$user->isAllowedAny( 'suppressrevision', 'viewsuppressed' ) ) { 00066 $conds[] = $this->mDb->bitAnd( 'ar_deleted', Revision::SUPPRESSED_USER ) . 00067 ' != ' . Revision::SUPPRESSED_USER; 00068 } 00069 00070 return array( 00071 'tables' => array( 'archive' ), 00072 'fields' => array( 00073 'ar_rev_id', 'ar_namespace', 'ar_title', 'ar_timestamp', 'ar_comment', 00074 'ar_minor_edit', 'ar_user', 'ar_user_text', 'ar_deleted' 00075 ), 00076 'conds' => $conds, 00077 'options' => array( 'USE INDEX' => $index ) 00078 ); 00079 } 00080 00081 function getUserCond() { 00082 $condition = array(); 00083 00084 $condition['ar_user_text'] = $this->target; 00085 $index = 'usertext_timestamp'; 00086 00087 return array( $index, $condition ); 00088 } 00089 00090 function getIndexField() { 00091 return 'ar_timestamp'; 00092 } 00093 00094 function getStartBody() { 00095 return "<ul>\n"; 00096 } 00097 00098 function getEndBody() { 00099 return "</ul>\n"; 00100 } 00101 00102 function getNavigationBar() { 00103 if ( isset( $this->mNavigationBar ) ) { 00104 return $this->mNavigationBar; 00105 } 00106 00107 $linkTexts = array( 00108 'prev' => $this->msg( 'pager-newer-n' )->numParams( $this->mLimit )->escaped(), 00109 'next' => $this->msg( 'pager-older-n' )->numParams( $this->mLimit )->escaped(), 00110 'first' => $this->msg( 'histlast' )->escaped(), 00111 'last' => $this->msg( 'histfirst' )->escaped() 00112 ); 00113 00114 $pagingLinks = $this->getPagingLinks( $linkTexts ); 00115 $limitLinks = $this->getLimitLinks(); 00116 $lang = $this->getLanguage(); 00117 $limits = $lang->pipeList( $limitLinks ); 00118 00119 $firstLast = $lang->pipeList( array( $pagingLinks['first'], $pagingLinks['last'] ) ); 00120 $firstLast = $this->msg( 'parentheses' )->rawParams( $firstLast )->escaped(); 00121 $prevNext = $this->msg( 'viewprevnext' ) 00122 ->rawParams( 00123 $pagingLinks['prev'], 00124 $pagingLinks['next'], 00125 $limits 00126 )->escaped(); 00127 $separator = $this->msg( 'word-separator' )->escaped(); 00128 $this->mNavigationBar = $firstLast . $separator . $prevNext; 00129 00130 return $this->mNavigationBar; 00131 } 00132 00133 function getNamespaceCond() { 00134 if ( $this->namespace !== '' ) { 00135 return array( 'ar_namespace' => (int)$this->namespace ); 00136 } else { 00137 return array(); 00138 } 00139 } 00140 00153 function formatRow( $row ) { 00154 wfProfileIn( __METHOD__ ); 00155 00156 $page = Title::makeTitle( $row->ar_namespace, $row->ar_title ); 00157 00158 $rev = new Revision( array( 00159 'title' => $page, 00160 'id' => $row->ar_rev_id, 00161 'comment' => $row->ar_comment, 00162 'user' => $row->ar_user, 00163 'user_text' => $row->ar_user_text, 00164 'timestamp' => $row->ar_timestamp, 00165 'minor_edit' => $row->ar_minor_edit, 00166 'deleted' => $row->ar_deleted, 00167 ) ); 00168 00169 $undelete = SpecialPage::getTitleFor( 'Undelete' ); 00170 00171 $logs = SpecialPage::getTitleFor( 'Log' ); 00172 $dellog = Linker::linkKnown( 00173 $logs, 00174 $this->messages['deletionlog'], 00175 array(), 00176 array( 00177 'type' => 'delete', 00178 'page' => $page->getPrefixedText() 00179 ) 00180 ); 00181 00182 $reviewlink = Linker::linkKnown( 00183 SpecialPage::getTitleFor( 'Undelete', $page->getPrefixedDBkey() ), 00184 $this->messages['undeleteviewlink'] 00185 ); 00186 00187 $user = $this->getUser(); 00188 00189 if ( $user->isAllowed( 'deletedtext' ) ) { 00190 $last = Linker::linkKnown( 00191 $undelete, 00192 $this->messages['diff'], 00193 array(), 00194 array( 00195 'target' => $page->getPrefixedText(), 00196 'timestamp' => $rev->getTimestamp(), 00197 'diff' => 'prev' 00198 ) 00199 ); 00200 } else { 00201 $last = $this->messages['diff']; 00202 } 00203 00204 $comment = Linker::revComment( $rev ); 00205 $date = $this->getLanguage()->userTimeAndDate( $rev->getTimestamp(), $user ); 00206 $date = htmlspecialchars( $date ); 00207 00208 if ( !$user->isAllowed( 'undelete' ) || !$rev->userCan( Revision::DELETED_TEXT, $user ) ) { 00209 $link = $date; // unusable link 00210 } else { 00211 $link = Linker::linkKnown( 00212 $undelete, 00213 $date, 00214 array( 'class' => 'mw-changeslist-date' ), 00215 array( 00216 'target' => $page->getPrefixedText(), 00217 'timestamp' => $rev->getTimestamp() 00218 ) 00219 ); 00220 } 00221 // Style deleted items 00222 if ( $rev->isDeleted( Revision::DELETED_TEXT ) ) { 00223 $link = '<span class="history-deleted">' . $link . '</span>'; 00224 } 00225 00226 $pagelink = Linker::link( 00227 $page, 00228 null, 00229 array( 'class' => 'mw-changeslist-title' ) 00230 ); 00231 00232 if ( $rev->isMinor() ) { 00233 $mflag = ChangesList::flag( 'minor' ); 00234 } else { 00235 $mflag = ''; 00236 } 00237 00238 // Revision delete link 00239 $del = Linker::getRevDeleteLink( $user, $rev, $page ); 00240 if ( $del ) { 00241 $del .= ' '; 00242 } 00243 00244 $tools = Html::rawElement( 00245 'span', 00246 array( 'class' => 'mw-deletedcontribs-tools' ), 00247 $this->msg( 'parentheses' )->rawParams( $this->getLanguage()->pipeList( 00248 array( $last, $dellog, $reviewlink ) ) )->escaped() 00249 ); 00250 00251 $separator = '<span class="mw-changeslist-separator">. .</span>'; 00252 $ret = "{$del}{$link} {$tools} {$separator} {$mflag} {$pagelink} {$comment}"; 00253 00254 # Denote if username is redacted for this edit 00255 if ( $rev->isDeleted( Revision::DELETED_USER ) ) { 00256 $ret .= " <strong>" . $this->msg( 'rev-deleted-user-contribs' )->escaped() . "</strong>"; 00257 } 00258 00259 $ret = Html::rawElement( 'li', array(), $ret ) . "\n"; 00260 00261 wfProfileOut( __METHOD__ ); 00262 00263 return $ret; 00264 } 00265 00271 public function getDatabase() { 00272 return $this->mDb; 00273 } 00274 } 00275 00276 class DeletedContributionsPage extends SpecialPage { 00277 function __construct() { 00278 parent::__construct( 'DeletedContributions', 'deletedhistory', 00279 /*listed*/true, /*function*/false, /*file*/false ); 00280 } 00281 00288 function execute( $par ) { 00289 $this->setHeaders(); 00290 $this->outputHeader(); 00291 00292 $user = $this->getUser(); 00293 00294 if ( !$this->userCanExecute( $user ) ) { 00295 $this->displayRestrictionError(); 00296 00297 return; 00298 } 00299 00300 $request = $this->getRequest(); 00301 $out = $this->getOutput(); 00302 $out->setPageTitle( $this->msg( 'deletedcontributions-title' ) ); 00303 00304 $options = array(); 00305 00306 if ( $par !== null ) { 00307 $target = $par; 00308 } else { 00309 $target = $request->getVal( 'target' ); 00310 } 00311 00312 if ( !strlen( $target ) ) { 00313 $out->addHTML( $this->getForm( '' ) ); 00314 00315 return; 00316 } 00317 00318 $options['limit'] = $request->getInt( 'limit', $this->getConfig()->get( 'QueryPageDefaultLimit' ) ); 00319 $options['target'] = $target; 00320 00321 $userObj = User::newFromName( $target, false ); 00322 if ( !$userObj ) { 00323 $out->addHTML( $this->getForm( '' ) ); 00324 00325 return; 00326 } 00327 $this->getSkin()->setRelevantUser( $userObj ); 00328 00329 $target = $userObj->getName(); 00330 $out->addSubtitle( $this->getSubTitle( $userObj ) ); 00331 00332 if ( ( $ns = $request->getVal( 'namespace', null ) ) !== null && $ns !== '' ) { 00333 $options['namespace'] = intval( $ns ); 00334 } else { 00335 $options['namespace'] = ''; 00336 } 00337 00338 $out->addHTML( $this->getForm( $options ) ); 00339 00340 $pager = new DeletedContribsPager( $this->getContext(), $target, $options['namespace'] ); 00341 if ( !$pager->getNumRows() ) { 00342 $out->addWikiMsg( 'nocontribs' ); 00343 00344 return; 00345 } 00346 00347 # Show a message about slave lag, if applicable 00348 $lag = wfGetLB()->safeGetLag( $pager->getDatabase() ); 00349 if ( $lag > 0 ) { 00350 $out->showLagWarning( $lag ); 00351 } 00352 00353 $out->addHTML( 00354 '<p>' . $pager->getNavigationBar() . '</p>' . 00355 $pager->getBody() . 00356 '<p>' . $pager->getNavigationBar() . '</p>' ); 00357 00358 # If there were contributions, and it was a valid user or IP, show 00359 # the appropriate "footer" message - WHOIS tools, etc. 00360 if ( $target != 'newbies' ) { 00361 $message = IP::isIPAddress( $target ) ? 00362 'sp-contributions-footer-anon' : 00363 'sp-contributions-footer'; 00364 00365 if ( !$this->msg( $message )->isDisabled() ) { 00366 $out->wrapWikiMsg( 00367 "<div class='mw-contributions-footer'>\n$1\n</div>", 00368 array( $message, $target ) 00369 ); 00370 } 00371 } 00372 } 00373 00380 function getSubTitle( $userObj ) { 00381 if ( $userObj->isAnon() ) { 00382 $user = htmlspecialchars( $userObj->getName() ); 00383 } else { 00384 $user = Linker::link( $userObj->getUserPage(), htmlspecialchars( $userObj->getName() ) ); 00385 } 00386 $links = ''; 00387 $nt = $userObj->getUserPage(); 00388 $id = $userObj->getID(); 00389 $talk = $nt->getTalkPage(); 00390 if ( $talk ) { 00391 # Talk page link 00392 $tools[] = Linker::link( $talk, $this->msg( 'sp-contributions-talk' )->escaped() ); 00393 if ( ( $id !== null ) || ( $id === null && IP::isIPAddress( $nt->getText() ) ) ) { 00394 # Block / Change block / Unblock links 00395 if ( $this->getUser()->isAllowed( 'block' ) ) { 00396 if ( $userObj->isBlocked() ) { 00397 $tools[] = Linker::linkKnown( # Change block link 00398 SpecialPage::getTitleFor( 'Block', $nt->getDBkey() ), 00399 $this->msg( 'change-blocklink' )->escaped() 00400 ); 00401 $tools[] = Linker::linkKnown( # Unblock link 00402 SpecialPage::getTitleFor( 'BlockList' ), 00403 $this->msg( 'unblocklink' )->escaped(), 00404 array(), 00405 array( 00406 'action' => 'unblock', 00407 'ip' => $nt->getDBkey() 00408 ) 00409 ); 00410 } else { 00411 # User is not blocked 00412 $tools[] = Linker::linkKnown( # Block link 00413 SpecialPage::getTitleFor( 'Block', $nt->getDBkey() ), 00414 $this->msg( 'blocklink' )->escaped() 00415 ); 00416 } 00417 } 00418 # Block log link 00419 $tools[] = Linker::linkKnown( 00420 SpecialPage::getTitleFor( 'Log' ), 00421 $this->msg( 'sp-contributions-blocklog' )->escaped(), 00422 array(), 00423 array( 00424 'type' => 'block', 00425 'page' => $nt->getPrefixedText() 00426 ) 00427 ); 00428 # Suppression log link (bug 59120) 00429 if ( $this->getUser()->isAllowed( 'suppressionlog' ) ) { 00430 $tools[] = Linker::linkKnown( 00431 SpecialPage::getTitleFor( 'Log', 'suppress' ), 00432 $this->msg( 'sp-contributions-suppresslog' )->escaped(), 00433 array(), 00434 array( 'offender' => $userObj->getName() ) 00435 ); 00436 } 00437 } 00438 00439 # Uploads 00440 $tools[] = Linker::linkKnown( 00441 SpecialPage::getTitleFor( 'Listfiles', $userObj->getName() ), 00442 $this->msg( 'sp-contributions-uploads' )->escaped() 00443 ); 00444 00445 # Other logs link 00446 $tools[] = Linker::linkKnown( 00447 SpecialPage::getTitleFor( 'Log' ), 00448 $this->msg( 'sp-contributions-logs' )->escaped(), 00449 array(), 00450 array( 'user' => $nt->getText() ) 00451 ); 00452 # Link to contributions 00453 $tools[] = Linker::linkKnown( 00454 SpecialPage::getTitleFor( 'Contributions', $nt->getDBkey() ), 00455 $this->msg( 'sp-deletedcontributions-contribs' )->escaped() 00456 ); 00457 00458 # Add a link to change user rights for privileged users 00459 $userrightsPage = new UserrightsPage(); 00460 $userrightsPage->setContext( $this->getContext() ); 00461 if ( $userrightsPage->userCanChangeRights( $userObj ) ) { 00462 $tools[] = Linker::linkKnown( 00463 SpecialPage::getTitleFor( 'Userrights', $nt->getDBkey() ), 00464 $this->msg( 'sp-contributions-userrights' )->escaped() 00465 ); 00466 } 00467 00468 wfRunHooks( 'ContributionsToolLinks', array( $id, $nt, &$tools ) ); 00469 00470 $links = $this->getLanguage()->pipeList( $tools ); 00471 00472 // Show a note if the user is blocked and display the last block log entry. 00473 $block = Block::newFromTarget( $userObj, $userObj ); 00474 if ( !is_null( $block ) && $block->getType() != Block::TYPE_AUTO ) { 00475 if ( $block->getType() == Block::TYPE_RANGE ) { 00476 $nt = MWNamespace::getCanonicalName( NS_USER ) . ':' . $block->getTarget(); 00477 } 00478 00479 // LogEventsList::showLogExtract() wants the first parameter by ref 00480 $out = $this->getOutput(); 00481 LogEventsList::showLogExtract( 00482 $out, 00483 'block', 00484 $nt, 00485 '', 00486 array( 00487 'lim' => 1, 00488 'showIfEmpty' => false, 00489 'msgKey' => array( 00490 'sp-contributions-blocked-notice', 00491 $userObj->getName() # Support GENDER in 'sp-contributions-blocked-notice' 00492 ), 00493 'offset' => '' # don't use $this->getRequest() parameter offset 00494 ) 00495 ); 00496 } 00497 } 00498 00499 return $this->msg( 'contribsub2' )->rawParams( $user, $links )->params( $userObj->getName() ); 00500 } 00501 00507 function getForm( $options ) { 00508 $options['title'] = $this->getPageTitle()->getPrefixedText(); 00509 if ( !isset( $options['target'] ) ) { 00510 $options['target'] = ''; 00511 } else { 00512 $options['target'] = str_replace( '_', ' ', $options['target'] ); 00513 } 00514 00515 if ( !isset( $options['namespace'] ) ) { 00516 $options['namespace'] = ''; 00517 } 00518 00519 if ( !isset( $options['contribs'] ) ) { 00520 $options['contribs'] = 'user'; 00521 } 00522 00523 if ( $options['contribs'] == 'newbie' ) { 00524 $options['target'] = ''; 00525 } 00526 00527 $f = Xml::openElement( 'form', array( 'method' => 'get', 'action' => wfScript() ) ); 00528 00529 foreach ( $options as $name => $value ) { 00530 if ( in_array( $name, array( 'namespace', 'target', 'contribs' ) ) ) { 00531 continue; 00532 } 00533 $f .= "\t" . Html::hidden( $name, $value ) . "\n"; 00534 } 00535 00536 $f .= Xml::openElement( 'fieldset' ); 00537 $f .= Xml::element( 'legend', array(), $this->msg( 'sp-contributions-search' )->text() ); 00538 $f .= Xml::tags( 00539 'label', 00540 array( 'for' => 'target' ), 00541 $this->msg( 'sp-contributions-username' )->parse() 00542 ) . ' '; 00543 $f .= Html::input( 00544 'target', 00545 $options['target'], 00546 'text', 00547 array( 00548 'size' => '20', 00549 'required' => '' 00550 ) + ( $options['target'] ? array() : array( 'autofocus' ) ) 00551 ) . ' '; 00552 $f .= Html::namespaceSelector( 00553 array( 00554 'selected' => $options['namespace'], 00555 'all' => '', 00556 'label' => $this->msg( 'namespace' )->text() 00557 ), 00558 array( 00559 'name' => 'namespace', 00560 'id' => 'namespace', 00561 'class' => 'namespaceselector', 00562 ) 00563 ) . ' '; 00564 $f .= Xml::submitButton( $this->msg( 'sp-contributions-submit' )->text() ); 00565 $f .= Xml::closeElement( 'fieldset' ); 00566 $f .= Xml::closeElement( 'form' ); 00567 00568 return $f; 00569 } 00570 00571 protected function getGroupName() { 00572 return 'users'; 00573 } 00574 }