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