MediaWiki
REL1_20
|
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 $rev = new Revision( array( 00139 'id' => $row->ar_rev_id, 00140 'comment' => $row->ar_comment, 00141 'user' => $row->ar_user, 00142 'user_text' => $row->ar_user_text, 00143 'timestamp' => $row->ar_timestamp, 00144 'minor_edit' => $row->ar_minor_edit, 00145 'deleted' => $row->ar_deleted, 00146 ) ); 00147 00148 $page = Title::makeTitle( $row->ar_namespace, $row->ar_title ); 00149 00150 $undelete = SpecialPage::getTitleFor( 'Undelete' ); 00151 00152 $logs = SpecialPage::getTitleFor( 'Log' ); 00153 $dellog = Linker::linkKnown( 00154 $logs, 00155 $this->messages['deletionlog'], 00156 array(), 00157 array( 00158 'type' => 'delete', 00159 'page' => $page->getPrefixedText() 00160 ) 00161 ); 00162 00163 $reviewlink = Linker::linkKnown( 00164 SpecialPage::getTitleFor( 'Undelete', $page->getPrefixedDBkey() ), 00165 $this->messages['undeleteviewlink'] 00166 ); 00167 00168 $user = $this->getUser(); 00169 00170 if( $user->isAllowed('deletedtext') ) { 00171 $last = Linker::linkKnown( 00172 $undelete, 00173 $this->messages['diff'], 00174 array(), 00175 array( 00176 'target' => $page->getPrefixedText(), 00177 'timestamp' => $rev->getTimestamp(), 00178 'diff' => 'prev' 00179 ) 00180 ); 00181 } else { 00182 $last = $this->messages['diff']; 00183 } 00184 00185 $comment = Linker::revComment( $rev ); 00186 $date = htmlspecialchars( $this->getLanguage()->userTimeAndDate( $rev->getTimestamp(), $user ) ); 00187 00188 if( !$user->isAllowed( 'undelete' ) || !$rev->userCan( Revision::DELETED_TEXT, $user ) ) { 00189 $link = $date; // unusable link 00190 } else { 00191 $link = Linker::linkKnown( 00192 $undelete, 00193 $date, 00194 array( 'class' => 'mw-changeslist-date' ), 00195 array( 00196 'target' => $page->getPrefixedText(), 00197 'timestamp' => $rev->getTimestamp() 00198 ) 00199 ); 00200 } 00201 // Style deleted items 00202 if( $rev->isDeleted( Revision::DELETED_TEXT ) ) { 00203 $link = '<span class="history-deleted">' . $link . '</span>'; 00204 } 00205 00206 $pagelink = Linker::link( 00207 $page, 00208 null, 00209 array( 'class' => 'mw-changeslist-title' ) 00210 ); 00211 00212 if( $rev->isMinor() ) { 00213 $mflag = ChangesList::flag( 'minor' ); 00214 } else { 00215 $mflag = ''; 00216 } 00217 00218 // Revision delete link 00219 $del = Linker::getRevDeleteLink( $user, $rev, $page ); 00220 if ( $del ) $del .= ' '; 00221 00222 $tools = Html::rawElement( 00223 'span', 00224 array( 'class' => 'mw-deletedcontribs-tools' ), 00225 $this->msg( 'parentheses' )->rawParams( $this->getLanguage()->pipeList( 00226 array( $last, $dellog, $reviewlink ) ) )->escaped() 00227 ); 00228 00229 $separator = '<span class="mw-changeslist-separator">. .</span>'; 00230 $ret = "{$del}{$link} {$tools} {$separator} {$mflag} {$pagelink} {$comment}"; 00231 00232 # Denote if username is redacted for this edit 00233 if( $rev->isDeleted( Revision::DELETED_USER ) ) { 00234 $ret .= " <strong>" . $this->msg( 'rev-deleted-user-contribs' )->escaped() . "</strong>"; 00235 } 00236 00237 $ret = Html::rawElement( 'li', array(), $ret ) . "\n"; 00238 00239 wfProfileOut( __METHOD__ ); 00240 return $ret; 00241 } 00242 00248 public function getDatabase() { 00249 return $this->mDb; 00250 } 00251 } 00252 00253 class DeletedContributionsPage extends SpecialPage { 00254 function __construct() { 00255 parent::__construct( 'DeletedContributions', 'deletedhistory', 00256 /*listed*/ true, /*function*/ false, /*file*/ false ); 00257 } 00258 00265 function execute( $par ) { 00266 global $wgQueryPageDefaultLimit; 00267 $this->setHeaders(); 00268 $this->outputHeader(); 00269 00270 $user = $this->getUser(); 00271 00272 if ( !$this->userCanExecute( $user ) ) { 00273 $this->displayRestrictionError(); 00274 return; 00275 } 00276 00277 $request = $this->getRequest(); 00278 $out = $this->getOutput(); 00279 $out->setPageTitle( $this->msg( 'deletedcontributions-title' ) ); 00280 00281 $options = array(); 00282 00283 if ( $par !== null ) { 00284 $target = $par; 00285 } else { 00286 $target = $request->getVal( 'target' ); 00287 } 00288 00289 if ( !strlen( $target ) ) { 00290 $out->addHTML( $this->getForm( '' ) ); 00291 return; 00292 } 00293 00294 $options['limit'] = $request->getInt( 'limit', $wgQueryPageDefaultLimit ); 00295 $options['target'] = $target; 00296 00297 $userObj = User::newFromName( $target, false ); 00298 if ( !$userObj ) { 00299 $out->addHTML( $this->getForm( '' ) ); 00300 return; 00301 } 00302 $this->getSkin()->setRelevantUser( $userObj ); 00303 00304 $target = $userObj->getName(); 00305 $out->addSubtitle( $this->getSubTitle( $userObj ) ); 00306 00307 if ( ( $ns = $request->getVal( 'namespace', null ) ) !== null && $ns !== '' ) { 00308 $options['namespace'] = intval( $ns ); 00309 } else { 00310 $options['namespace'] = ''; 00311 } 00312 00313 $out->addHTML( $this->getForm( $options ) ); 00314 00315 $pager = new DeletedContribsPager( $this->getContext(), $target, $options['namespace'] ); 00316 if ( !$pager->getNumRows() ) { 00317 $out->addWikiMsg( 'nocontribs' ); 00318 return; 00319 } 00320 00321 # Show a message about slave lag, if applicable 00322 $lag = wfGetLB()->safeGetLag( $pager->getDatabase() ); 00323 if( $lag > 0 ) 00324 $out->showLagWarning( $lag ); 00325 00326 $out->addHTML( 00327 '<p>' . $pager->getNavigationBar() . '</p>' . 00328 $pager->getBody() . 00329 '<p>' . $pager->getNavigationBar() . '</p>' ); 00330 00331 # If there were contributions, and it was a valid user or IP, show 00332 # the appropriate "footer" message - WHOIS tools, etc. 00333 if( $target != 'newbies' ) { 00334 $message = IP::isIPAddress( $target ) 00335 ? 'sp-contributions-footer-anon' 00336 : 'sp-contributions-footer'; 00337 00338 if( !$this->msg( $message )->isDisabled() ) { 00339 $out->wrapWikiMsg( "<div class='mw-contributions-footer'>\n$1\n</div>", array( $message, $target ) ); 00340 } 00341 } 00342 } 00343 00350 function getSubTitle( $userObj ) { 00351 if ( $userObj->isAnon() ) { 00352 $user = htmlspecialchars( $userObj->getName() ); 00353 } else { 00354 $user = Linker::link( $userObj->getUserPage(), htmlspecialchars( $userObj->getName() ) ); 00355 } 00356 $links = ''; 00357 $nt = $userObj->getUserPage(); 00358 $id = $userObj->getID(); 00359 $talk = $nt->getTalkPage(); 00360 if( $talk ) { 00361 # Talk page link 00362 $tools[] = Linker::link( $talk, $this->msg( 'sp-contributions-talk' )->escaped() ); 00363 if( ( $id !== null ) || ( $id === null && IP::isIPAddress( $nt->getText() ) ) ) { 00364 if( $this->getUser()->isAllowed( 'block' ) ) { # Block / Change block / Unblock links 00365 if ( $userObj->isBlocked() ) { 00366 $tools[] = Linker::linkKnown( # Change block link 00367 SpecialPage::getTitleFor( 'Block', $nt->getDBkey() ), 00368 $this->msg( 'change-blocklink' )->escaped() 00369 ); 00370 $tools[] = Linker::linkKnown( # Unblock link 00371 SpecialPage::getTitleFor( 'BlockList' ), 00372 $this->msg( 'unblocklink' )->escaped(), 00373 array(), 00374 array( 00375 'action' => 'unblock', 00376 'ip' => $nt->getDBkey() 00377 ) 00378 ); 00379 } 00380 else { # User is not blocked 00381 $tools[] = Linker::linkKnown( # Block link 00382 SpecialPage::getTitleFor( 'Block', $nt->getDBkey() ), 00383 $this->msg( 'blocklink' )->escaped() 00384 ); 00385 } 00386 } 00387 # Block log link 00388 $tools[] = Linker::linkKnown( 00389 SpecialPage::getTitleFor( 'Log' ), 00390 $this->msg( 'sp-contributions-blocklog' )->escaped(), 00391 array(), 00392 array( 00393 'type' => 'block', 00394 'page' => $nt->getPrefixedText() 00395 ) 00396 ); 00397 } 00398 00399 # Uploads 00400 $tools[] = Linker::linkKnown( 00401 SpecialPage::getTitleFor( 'Listfiles', $userObj->getName() ), 00402 $this->msg( 'sp-contributions-uploads' )->escaped() 00403 ); 00404 00405 # Other logs link 00406 $tools[] = Linker::linkKnown( 00407 SpecialPage::getTitleFor( 'Log' ), 00408 $this->msg( 'sp-contributions-logs' )->escaped(), 00409 array(), 00410 array( 'user' => $nt->getText() ) 00411 ); 00412 # Link to contributions 00413 $tools[] = Linker::linkKnown( 00414 SpecialPage::getTitleFor( 'Contributions', $nt->getDBkey() ), 00415 $this->msg( 'sp-deletedcontributions-contribs' )->escaped() 00416 ); 00417 00418 # Add a link to change user rights for privileged users 00419 $userrightsPage = new UserrightsPage(); 00420 $userrightsPage->setContext( $this->getContext() ); 00421 if( $userrightsPage->userCanChangeRights( $userObj ) ) { 00422 $tools[] = Linker::linkKnown( 00423 SpecialPage::getTitleFor( 'Userrights', $nt->getDBkey() ), 00424 $this->msg( 'sp-contributions-userrights' )->escaped() 00425 ); 00426 } 00427 00428 wfRunHooks( 'ContributionsToolLinks', array( $id, $nt, &$tools ) ); 00429 00430 $links = $this->getLanguage()->pipeList( $tools ); 00431 00432 // Show a note if the user is blocked and display the last block log entry. 00433 if ( $userObj->isBlocked() ) { 00434 $out = $this->getOutput(); // LogEventsList::showLogExtract() wants the first parameter by ref 00435 LogEventsList::showLogExtract( 00436 $out, 00437 'block', 00438 $nt, 00439 '', 00440 array( 00441 'lim' => 1, 00442 'showIfEmpty' => false, 00443 'msgKey' => array( 00444 'sp-contributions-blocked-notice', 00445 $nt->getText() # Support GENDER in 'sp-contributions-blocked-notice' 00446 ), 00447 'offset' => '' # don't use $this->getRequest() parameter offset 00448 ) 00449 ); 00450 } 00451 } 00452 00453 // Old message 'contribsub' had one parameter, but that doesn't work for 00454 // languages that want to put the "for" bit right after $user but before 00455 // $links. If 'contribsub' is around, use it for reverse compatibility, 00456 // otherwise use 'contribsub2'. 00457 $oldMsg = $this->msg( 'contribsub' ); 00458 if ( $oldMsg->exists() ) { 00459 return $oldMsg->rawParams( "$user ($links)" ); 00460 } else { 00461 return $this->msg( 'contribsub2' )->rawParams( $user, $links ); 00462 } 00463 } 00464 00470 function getForm( $options ) { 00471 global $wgScript; 00472 00473 $options['title'] = $this->getTitle()->getPrefixedText(); 00474 if ( !isset( $options['target'] ) ) { 00475 $options['target'] = ''; 00476 } else { 00477 $options['target'] = str_replace( '_' , ' ' , $options['target'] ); 00478 } 00479 00480 if ( !isset( $options['namespace'] ) ) { 00481 $options['namespace'] = ''; 00482 } 00483 00484 if ( !isset( $options['contribs'] ) ) { 00485 $options['contribs'] = 'user'; 00486 } 00487 00488 if ( $options['contribs'] == 'newbie' ) { 00489 $options['target'] = ''; 00490 } 00491 00492 $f = Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ); 00493 00494 foreach ( $options as $name => $value ) { 00495 if ( in_array( $name, array( 'namespace', 'target', 'contribs' ) ) ) { 00496 continue; 00497 } 00498 $f .= "\t" . Html::hidden( $name, $value ) . "\n"; 00499 } 00500 00501 $f .= Xml::openElement( 'fieldset' ) . 00502 Xml::element( 'legend', array(), $this->msg( 'sp-contributions-search' )->text() ) . 00503 Xml::tags( 'label', array( 'for' => 'target' ), $this->msg( 'sp-contributions-username' )->parse() ) . ' ' . 00504 Html::input( 'target', $options['target'], 'text', array( 00505 'size' => '20', 00506 'required' => '' 00507 ) + ( $options['target'] ? array() : array( 'autofocus' ) ) ) . ' '. 00508 Html::namespaceSelector( 00509 array( 00510 'selected' => $options['namespace'], 00511 'all' => '', 00512 'label' => $this->msg( 'namespace' )->text() 00513 ), array( 00514 'name' => 'namespace', 00515 'id' => 'namespace', 00516 'class' => 'namespaceselector', 00517 ) 00518 ) . ' ' . 00519 Xml::submitButton( $this->msg( 'sp-contributions-submit' )->text() ) . 00520 Xml::closeElement( 'fieldset' ) . 00521 Xml::closeElement( 'form' ); 00522 return $f; 00523 } 00524 }