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