MediaWiki
REL1_22
|
00001 <?php 00028 class DeletedContribsPager extends IndexPager { 00029 public $mDefaultDirection = true; 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->isAllowed( 'suppressrevision' ) ) { 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 global $wgQueryPageDefaultLimit; 00290 00291 $this->setHeaders(); 00292 $this->outputHeader(); 00293 00294 $user = $this->getUser(); 00295 00296 if ( !$this->userCanExecute( $user ) ) { 00297 $this->displayRestrictionError(); 00298 00299 return; 00300 } 00301 00302 $request = $this->getRequest(); 00303 $out = $this->getOutput(); 00304 $out->setPageTitle( $this->msg( 'deletedcontributions-title' ) ); 00305 00306 $options = array(); 00307 00308 if ( $par !== null ) { 00309 $target = $par; 00310 } else { 00311 $target = $request->getVal( 'target' ); 00312 } 00313 00314 if ( !strlen( $target ) ) { 00315 $out->addHTML( $this->getForm( '' ) ); 00316 00317 return; 00318 } 00319 00320 $options['limit'] = $request->getInt( 'limit', $wgQueryPageDefaultLimit ); 00321 $options['target'] = $target; 00322 00323 $userObj = User::newFromName( $target, false ); 00324 if ( !$userObj ) { 00325 $out->addHTML( $this->getForm( '' ) ); 00326 00327 return; 00328 } 00329 $this->getSkin()->setRelevantUser( $userObj ); 00330 00331 $target = $userObj->getName(); 00332 $out->addSubtitle( $this->getSubTitle( $userObj ) ); 00333 00334 if ( ( $ns = $request->getVal( 'namespace', null ) ) !== null && $ns !== '' ) { 00335 $options['namespace'] = intval( $ns ); 00336 } else { 00337 $options['namespace'] = ''; 00338 } 00339 00340 $out->addHTML( $this->getForm( $options ) ); 00341 00342 $pager = new DeletedContribsPager( $this->getContext(), $target, $options['namespace'] ); 00343 if ( !$pager->getNumRows() ) { 00344 $out->addWikiMsg( 'nocontribs' ); 00345 00346 return; 00347 } 00348 00349 # Show a message about slave lag, if applicable 00350 $lag = wfGetLB()->safeGetLag( $pager->getDatabase() ); 00351 if ( $lag > 0 ) { 00352 $out->showLagWarning( $lag ); 00353 } 00354 00355 $out->addHTML( 00356 '<p>' . $pager->getNavigationBar() . '</p>' . 00357 $pager->getBody() . 00358 '<p>' . $pager->getNavigationBar() . '</p>' ); 00359 00360 # If there were contributions, and it was a valid user or IP, show 00361 # the appropriate "footer" message - WHOIS tools, etc. 00362 if ( $target != 'newbies' ) { 00363 $message = IP::isIPAddress( $target ) ? 00364 'sp-contributions-footer-anon' : 00365 'sp-contributions-footer'; 00366 00367 if ( !$this->msg( $message )->isDisabled() ) { 00368 $out->wrapWikiMsg( 00369 "<div class='mw-contributions-footer'>\n$1\n</div>", 00370 array( $message, $target ) 00371 ); 00372 } 00373 } 00374 } 00375 00382 function getSubTitle( $userObj ) { 00383 if ( $userObj->isAnon() ) { 00384 $user = htmlspecialchars( $userObj->getName() ); 00385 } else { 00386 $user = Linker::link( $userObj->getUserPage(), htmlspecialchars( $userObj->getName() ) ); 00387 } 00388 $links = ''; 00389 $nt = $userObj->getUserPage(); 00390 $id = $userObj->getID(); 00391 $talk = $nt->getTalkPage(); 00392 if ( $talk ) { 00393 # Talk page link 00394 $tools[] = Linker::link( $talk, $this->msg( 'sp-contributions-talk' )->escaped() ); 00395 if ( ( $id !== null ) || ( $id === null && IP::isIPAddress( $nt->getText() ) ) ) { 00396 # Block / Change block / Unblock links 00397 if ( $this->getUser()->isAllowed( 'block' ) ) { 00398 if ( $userObj->isBlocked() ) { 00399 $tools[] = Linker::linkKnown( # Change block link 00400 SpecialPage::getTitleFor( 'Block', $nt->getDBkey() ), 00401 $this->msg( 'change-blocklink' )->escaped() 00402 ); 00403 $tools[] = Linker::linkKnown( # Unblock link 00404 SpecialPage::getTitleFor( 'BlockList' ), 00405 $this->msg( 'unblocklink' )->escaped(), 00406 array(), 00407 array( 00408 'action' => 'unblock', 00409 'ip' => $nt->getDBkey() 00410 ) 00411 ); 00412 } else { 00413 # User is not blocked 00414 $tools[] = Linker::linkKnown( # Block link 00415 SpecialPage::getTitleFor( 'Block', $nt->getDBkey() ), 00416 $this->msg( 'blocklink' )->escaped() 00417 ); 00418 } 00419 } 00420 # Block log link 00421 $tools[] = Linker::linkKnown( 00422 SpecialPage::getTitleFor( 'Log' ), 00423 $this->msg( 'sp-contributions-blocklog' )->escaped(), 00424 array(), 00425 array( 00426 'type' => 'block', 00427 'page' => $nt->getPrefixedText() 00428 ) 00429 ); 00430 } 00431 00432 # Uploads 00433 $tools[] = Linker::linkKnown( 00434 SpecialPage::getTitleFor( 'Listfiles', $userObj->getName() ), 00435 $this->msg( 'sp-contributions-uploads' )->escaped() 00436 ); 00437 00438 # Other logs link 00439 $tools[] = Linker::linkKnown( 00440 SpecialPage::getTitleFor( 'Log' ), 00441 $this->msg( 'sp-contributions-logs' )->escaped(), 00442 array(), 00443 array( 'user' => $nt->getText() ) 00444 ); 00445 # Link to contributions 00446 $tools[] = Linker::linkKnown( 00447 SpecialPage::getTitleFor( 'Contributions', $nt->getDBkey() ), 00448 $this->msg( 'sp-deletedcontributions-contribs' )->escaped() 00449 ); 00450 00451 # Add a link to change user rights for privileged users 00452 $userrightsPage = new UserrightsPage(); 00453 $userrightsPage->setContext( $this->getContext() ); 00454 if ( $userrightsPage->userCanChangeRights( $userObj ) ) { 00455 $tools[] = Linker::linkKnown( 00456 SpecialPage::getTitleFor( 'Userrights', $nt->getDBkey() ), 00457 $this->msg( 'sp-contributions-userrights' )->escaped() 00458 ); 00459 } 00460 00461 wfRunHooks( 'ContributionsToolLinks', array( $id, $nt, &$tools ) ); 00462 00463 $links = $this->getLanguage()->pipeList( $tools ); 00464 00465 // Show a note if the user is blocked and display the last block log entry. 00466 if ( $userObj->isBlocked() ) { 00467 // LogEventsList::showLogExtract() wants the first parameter by ref 00468 $out = $this->getOutput(); 00469 LogEventsList::showLogExtract( 00470 $out, 00471 'block', 00472 $nt, 00473 '', 00474 array( 00475 'lim' => 1, 00476 'showIfEmpty' => false, 00477 'msgKey' => array( 00478 'sp-contributions-blocked-notice', 00479 $nt->getText() # Support GENDER in 'sp-contributions-blocked-notice' 00480 ), 00481 'offset' => '' # don't use $this->getRequest() parameter offset 00482 ) 00483 ); 00484 } 00485 } 00486 00487 return $this->msg( 'contribsub2' )->rawParams( $user, $links )->params( $userObj->getName() ); 00488 } 00489 00495 function getForm( $options ) { 00496 global $wgScript; 00497 00498 $options['title'] = $this->getTitle()->getPrefixedText(); 00499 if ( !isset( $options['target'] ) ) { 00500 $options['target'] = ''; 00501 } else { 00502 $options['target'] = str_replace( '_', ' ', $options['target'] ); 00503 } 00504 00505 if ( !isset( $options['namespace'] ) ) { 00506 $options['namespace'] = ''; 00507 } 00508 00509 if ( !isset( $options['contribs'] ) ) { 00510 $options['contribs'] = 'user'; 00511 } 00512 00513 if ( $options['contribs'] == 'newbie' ) { 00514 $options['target'] = ''; 00515 } 00516 00517 $f = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); 00518 00519 foreach ( $options as $name => $value ) { 00520 if ( in_array( $name, array( 'namespace', 'target', 'contribs' ) ) ) { 00521 continue; 00522 } 00523 $f .= "\t" . Html::hidden( $name, $value ) . "\n"; 00524 } 00525 00526 $f .= Xml::openElement( 'fieldset' ); 00527 $f .= Xml::element( 'legend', array(), $this->msg( 'sp-contributions-search' )->text() ); 00528 $f .= Xml::tags( 00529 'label', 00530 array( 'for' => 'target' ), 00531 $this->msg( 'sp-contributions-username' )->parse() 00532 ) . ' '; 00533 $f .= Html::input( 00534 'target', 00535 $options['target'], 00536 'text', 00537 array( 00538 'size' => '20', 00539 'required' => '' 00540 ) + ( $options['target'] ? array() : array( 'autofocus' ) ) 00541 ) . ' '; 00542 $f .= Html::namespaceSelector( 00543 array( 00544 'selected' => $options['namespace'], 00545 'all' => '', 00546 'label' => $this->msg( 'namespace' )->text() 00547 ), 00548 array( 00549 'name' => 'namespace', 00550 'id' => 'namespace', 00551 'class' => 'namespaceselector', 00552 ) 00553 ) . ' '; 00554 $f .= Xml::submitButton( $this->msg( 'sp-contributions-submit' )->text() ); 00555 $f .= Xml::closeElement( 'fieldset' ); 00556 $f .= Xml::closeElement( 'form' ); 00557 00558 return $f; 00559 } 00560 00561 protected function getGroupName() { 00562 return 'users'; 00563 } 00564 }