MediaWiki  REL1_20
SpecialDeletedContributions.php
Go to the documentation of this file.
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 }