MediaWiki  REL1_22
SpecialBlockList.php
Go to the documentation of this file.
00001 <?php
00029 class SpecialBlockList extends SpecialPage {
00030 
00031     protected $target, $options;
00032 
00033     function __construct() {
00034         parent::__construct( 'BlockList' );
00035     }
00036 
00042     public function execute( $par ) {
00043         $this->setHeaders();
00044         $this->outputHeader();
00045         $out = $this->getOutput();
00046         $lang = $this->getLanguage();
00047         $out->setPageTitle( $this->msg( 'ipblocklist' ) );
00048         $out->addModuleStyles( 'mediawiki.special' );
00049 
00050         $request = $this->getRequest();
00051         $par = $request->getVal( 'ip', $par );
00052         $this->target = trim( $request->getVal( 'wpTarget', $par ) );
00053 
00054         $this->options = $request->getArray( 'wpOptions', array() );
00055 
00056         $action = $request->getText( 'action' );
00057 
00058         if ( $action == 'unblock' || $action == 'submit' && $request->wasPosted() ) {
00059             # B/C @since 1.18: Unblock interface is now at Special:Unblock
00060             $title = SpecialPage::getTitleFor( 'Unblock', $this->target );
00061             $out->redirect( $title->getFullURL() );
00062 
00063             return;
00064         }
00065 
00066         # Just show the block list
00067         $fields = array(
00068             'Target' => array(
00069                 'type' => 'text',
00070                 'label-message' => 'ipadressorusername',
00071                 'tabindex' => '1',
00072                 'size' => '45',
00073                 'default' => $this->target,
00074             ),
00075             'Options' => array(
00076                 'type' => 'multiselect',
00077                 'options' => array(
00078                     $this->msg( 'blocklist-userblocks' )->text() => 'userblocks',
00079                     $this->msg( 'blocklist-tempblocks' )->text() => 'tempblocks',
00080                     $this->msg( 'blocklist-addressblocks' )->text() => 'addressblocks',
00081                     $this->msg( 'blocklist-rangeblocks' )->text() => 'rangeblocks',
00082                 ),
00083                 'flatlist' => true,
00084             ),
00085             'Limit' => array(
00086                 'class' => 'HTMLBlockedUsersItemSelect',
00087                 'label-message' => 'table_pager_limit_label',
00088                 'options' => array(
00089                     $lang->formatNum( 20 ) => 20,
00090                     $lang->formatNum( 50 ) => 50,
00091                     $lang->formatNum( 100 ) => 100,
00092                     $lang->formatNum( 250 ) => 250,
00093                     $lang->formatNum( 500 ) => 500,
00094                 ),
00095                 'name' => 'limit',
00096                 'default' => 50,
00097             ),
00098         );
00099         $context = new DerivativeContext( $this->getContext() );
00100         $context->setTitle( $this->getTitle() ); // Remove subpage
00101         $form = new HTMLForm( $fields, $context );
00102         $form->setMethod( 'get' );
00103         $form->setWrapperLegendMsg( 'ipblocklist-legend' );
00104         $form->setSubmitTextMsg( 'ipblocklist-submit' );
00105         $form->prepareForm();
00106 
00107         $form->displayForm( '' );
00108         $this->showList();
00109     }
00110 
00111     function showList() {
00112         # Purge expired entries on one in every 10 queries
00113         if ( !mt_rand( 0, 10 ) ) {
00114             Block::purgeExpired();
00115         }
00116 
00117         $conds = array();
00118         # Is the user allowed to see hidden blocks?
00119         if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
00120             $conds['ipb_deleted'] = 0;
00121         }
00122 
00123         if ( $this->target !== '' ) {
00124             list( $target, $type ) = Block::parseTarget( $this->target );
00125 
00126             switch ( $type ) {
00127                 case Block::TYPE_ID:
00128                 case Block::TYPE_AUTO:
00129                     $conds['ipb_id'] = $target;
00130                     break;
00131 
00132                 case Block::TYPE_IP:
00133                 case Block::TYPE_RANGE:
00134                     list( $start, $end ) = IP::parseRange( $target );
00135                     $dbr = wfGetDB( DB_SLAVE );
00136                     $conds[] = $dbr->makeList(
00137                         array(
00138                             'ipb_address' => $target,
00139                             Block::getRangeCond( $start, $end )
00140                         ),
00141                         LIST_OR
00142                     );
00143                     $conds['ipb_auto'] = 0;
00144                     break;
00145 
00146                 case Block::TYPE_USER:
00147                     $conds['ipb_address'] = $target->getName();
00148                     $conds['ipb_auto'] = 0;
00149                     break;
00150             }
00151         }
00152 
00153         # Apply filters
00154         if ( in_array( 'userblocks', $this->options ) ) {
00155             $conds['ipb_user'] = 0;
00156         }
00157         if ( in_array( 'tempblocks', $this->options ) ) {
00158             $conds['ipb_expiry'] = 'infinity';
00159         }
00160         if ( in_array( 'addressblocks', $this->options ) ) {
00161             $conds[] = "ipb_user != 0 OR ipb_range_end > ipb_range_start";
00162         }
00163         if ( in_array( 'rangeblocks', $this->options ) ) {
00164             $conds[] = "ipb_range_end = ipb_range_start";
00165         }
00166 
00167         # Check for other blocks, i.e. global/tor blocks
00168         $otherBlockLink = array();
00169         wfRunHooks( 'OtherBlockLogLink', array( &$otherBlockLink, $this->target ) );
00170 
00171         $out = $this->getOutput();
00172 
00173         # Show additional header for the local block only when other blocks exists.
00174         # Not necessary in a standard installation without such extensions enabled
00175         if ( count( $otherBlockLink ) ) {
00176             $out->addHTML(
00177                 Html::element( 'h2', array(), $this->msg( 'ipblocklist-localblock' )->text() ) . "\n"
00178             );
00179         }
00180 
00181         $pager = new BlockListPager( $this, $conds );
00182         if ( $pager->getNumRows() ) {
00183             $out->addHTML(
00184                 $pager->getNavigationBar() .
00185                     $pager->getBody() .
00186                     $pager->getNavigationBar()
00187             );
00188         } elseif ( $this->target ) {
00189             $out->addWikiMsg( 'ipblocklist-no-results' );
00190         } else {
00191             $out->addWikiMsg( 'ipblocklist-empty' );
00192         }
00193 
00194         if ( count( $otherBlockLink ) ) {
00195             $out->addHTML(
00196                 Html::rawElement(
00197                     'h2',
00198                     array(),
00199                     $this->msg( 'ipblocklist-otherblocks', count( $otherBlockLink ) )->parse()
00200                 ) . "\n"
00201             );
00202             $list = '';
00203             foreach ( $otherBlockLink as $link ) {
00204                 $list .= Html::rawElement( 'li', array(), $link ) . "\n";
00205             }
00206             $out->addHTML( Html::rawElement( 'ul', array( 'class' => 'mw-ipblocklist-otherblocks' ), $list ) . "\n" );
00207         }
00208     }
00209 
00210     protected function getGroupName() {
00211         return 'users';
00212     }
00213 }
00214 
00215 class BlockListPager extends TablePager {
00216     protected $conds;
00217     protected $page;
00218 
00223     function __construct( $page, $conds ) {
00224         $this->page = $page;
00225         $this->conds = $conds;
00226         $this->mDefaultDirection = true;
00227         parent::__construct( $page->getContext() );
00228     }
00229 
00230     function getFieldNames() {
00231         static $headers = null;
00232 
00233         if ( $headers == array() ) {
00234             $headers = array(
00235                 'ipb_timestamp' => 'blocklist-timestamp',
00236                 'ipb_target' => 'blocklist-target',
00237                 'ipb_expiry' => 'blocklist-expiry',
00238                 'ipb_by' => 'blocklist-by',
00239                 'ipb_params' => 'blocklist-params',
00240                 'ipb_reason' => 'blocklist-reason',
00241             );
00242             foreach ( $headers as $key => $val ) {
00243                 $headers[$key] = $this->msg( $val )->text();
00244             }
00245         }
00246 
00247         return $headers;
00248     }
00249 
00250     function formatValue( $name, $value ) {
00251         static $msg = null;
00252         if ( $msg === null ) {
00253             $msg = array(
00254                 'anononlyblock',
00255                 'createaccountblock',
00256                 'noautoblockblock',
00257                 'emailblock',
00258                 'blocklist-nousertalk',
00259                 'unblocklink',
00260                 'change-blocklink',
00261                 'infiniteblock',
00262             );
00263             $msg = array_combine( $msg, array_map( array( $this, 'msg' ), $msg ) );
00264         }
00265 
00267         $row = $this->mCurrentRow;
00268 
00269         $formatted = '';
00270 
00271         switch ( $name ) {
00272             case 'ipb_timestamp':
00273                 $formatted = $this->getLanguage()->userTimeAndDate( $value, $this->getUser() );
00274                 break;
00275 
00276             case 'ipb_target':
00277                 if ( $row->ipb_auto ) {
00278                     $formatted = $this->msg( 'autoblockid', $row->ipb_id )->parse();
00279                 } else {
00280                     list( $target, $type ) = Block::parseTarget( $row->ipb_address );
00281                     switch ( $type ) {
00282                         case Block::TYPE_USER:
00283                         case Block::TYPE_IP:
00284                             $formatted = Linker::userLink( $target->getId(), $target );
00285                             $formatted .= Linker::userToolLinks(
00286                                 $target->getId(),
00287                                 $target,
00288                                 false,
00289                                 Linker::TOOL_LINKS_NOBLOCK
00290                             );
00291                             break;
00292                         case Block::TYPE_RANGE:
00293                             $formatted = htmlspecialchars( $target );
00294                     }
00295                 }
00296                 break;
00297 
00298             case 'ipb_expiry':
00299                 $formatted = $this->getLanguage()->formatExpiry( $value, /* User preference timezone */true );
00300                 if ( $this->getUser()->isAllowed( 'block' ) ) {
00301                     if ( $row->ipb_auto ) {
00302                         $links[] = Linker::linkKnown(
00303                             SpecialPage::getTitleFor( 'Unblock' ),
00304                             $msg['unblocklink'],
00305                             array(),
00306                             array( 'wpTarget' => "#{$row->ipb_id}" )
00307                         );
00308                     } else {
00309                         $links[] = Linker::linkKnown(
00310                             SpecialPage::getTitleFor( 'Unblock', $row->ipb_address ),
00311                             $msg['unblocklink']
00312                         );
00313                         $links[] = Linker::linkKnown(
00314                             SpecialPage::getTitleFor( 'Block', $row->ipb_address ),
00315                             $msg['change-blocklink']
00316                         );
00317                     }
00318                     $formatted .= ' ' . Html::rawElement(
00319                         'span',
00320                         array( 'class' => 'mw-blocklist-actions' ),
00321                         $this->msg( 'parentheses' )->rawParams(
00322                             $this->getLanguage()->pipeList( $links ) )->escaped()
00323                     );
00324                 }
00325                 break;
00326 
00327             case 'ipb_by':
00328                 if ( isset( $row->by_user_name ) ) {
00329                     $formatted = Linker::userLink( $value, $row->by_user_name );
00330                     $formatted .= Linker::userToolLinks( $value, $row->by_user_name );
00331                 } else {
00332                     $formatted = htmlspecialchars( $row->ipb_by_text ); // foreign user?
00333                 }
00334                 break;
00335 
00336             case 'ipb_reason':
00337                 $formatted = Linker::formatComment( $value );
00338                 break;
00339 
00340             case 'ipb_params':
00341                 $properties = array();
00342                 if ( $row->ipb_anon_only ) {
00343                     $properties[] = $msg['anononlyblock'];
00344                 }
00345                 if ( $row->ipb_create_account ) {
00346                     $properties[] = $msg['createaccountblock'];
00347                 }
00348                 if ( $row->ipb_user && !$row->ipb_enable_autoblock ) {
00349                     $properties[] = $msg['noautoblockblock'];
00350                 }
00351 
00352                 if ( $row->ipb_block_email ) {
00353                     $properties[] = $msg['emailblock'];
00354                 }
00355 
00356                 if ( !$row->ipb_allow_usertalk ) {
00357                     $properties[] = $msg['blocklist-nousertalk'];
00358                 }
00359 
00360                 $formatted = $this->getLanguage()->commaList( $properties );
00361                 break;
00362 
00363             default:
00364                 $formatted = "Unable to format $name";
00365                 break;
00366         }
00367 
00368         return $formatted;
00369     }
00370 
00371     function getQueryInfo() {
00372         $info = array(
00373             'tables' => array( 'ipblocks', 'user' ),
00374             'fields' => array(
00375                 'ipb_id',
00376                 'ipb_address',
00377                 'ipb_user',
00378                 'ipb_by',
00379                 'ipb_by_text',
00380                 'by_user_name' => 'user_name',
00381                 'ipb_reason',
00382                 'ipb_timestamp',
00383                 'ipb_auto',
00384                 'ipb_anon_only',
00385                 'ipb_create_account',
00386                 'ipb_enable_autoblock',
00387                 'ipb_expiry',
00388                 'ipb_range_start',
00389                 'ipb_range_end',
00390                 'ipb_deleted',
00391                 'ipb_block_email',
00392                 'ipb_allow_usertalk',
00393             ),
00394             'conds' => $this->conds,
00395             'join_conds' => array( 'user' => array( 'LEFT JOIN', 'user_id = ipb_by' ) )
00396         );
00397 
00398         # Is the user allowed to see hidden blocks?
00399         if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
00400             $info['conds']['ipb_deleted'] = 0;
00401         }
00402 
00403         return $info;
00404     }
00405 
00406     public function getTableClass() {
00407         return 'TablePager mw-blocklist';
00408     }
00409 
00410     function getIndexField() {
00411         return 'ipb_timestamp';
00412     }
00413 
00414     function getDefaultSort() {
00415         return 'ipb_timestamp';
00416     }
00417 
00418     function isFieldSortable( $name ) {
00419         return false;
00420     }
00421 
00426     function preprocessResults( $result ) {
00427         wfProfileIn( __METHOD__ );
00428         # Do a link batch query
00429         $lb = new LinkBatch;
00430         $lb->setCaller( __METHOD__ );
00431 
00432         $userids = array();
00433 
00434         foreach ( $result as $row ) {
00435             $userids[] = $row->ipb_by;
00436 
00437             # Usernames and titles are in fact related by a simple substitution of space -> underscore
00438             # The last few lines of Title::secureAndSplit() tell the story.
00439             $name = str_replace( ' ', '_', $row->ipb_address );
00440             $lb->add( NS_USER, $name );
00441             $lb->add( NS_USER_TALK, $name );
00442         }
00443 
00444         $ua = UserArray::newFromIDs( $userids );
00445         foreach ( $ua as $user ) {
00446             $name = str_replace( ' ', '_', $user->getName() );
00447             $lb->add( NS_USER, $name );
00448             $lb->add( NS_USER_TALK, $name );
00449         }
00450 
00451         $lb->execute();
00452         wfProfileOut( __METHOD__ );
00453     }
00454 }
00455 
00461 class HTMLBlockedUsersItemSelect extends HTMLSelectField {
00470     function validate( $value, $alldata ) {
00471         if ( $value == '' ) {
00472             return true;
00473         }
00474 
00475         // Let folks pick an explicit limit not from our list, as long as it's a real numbr.
00476         if ( !in_array( $value, $this->mParams['options'] ) && $value == intval( $value ) && $value > 0 ) {
00477             // This adds the explicitly requested limit value to the drop-down,
00478             // then makes sure it's sorted correctly so when we output the list
00479             // later, the custom option doesn't just show up last.
00480             $this->mParams['options'][$this->mParent->getLanguage()->formatNum( $value )] = intval( $value );
00481             asort( $this->mParams['options'] );
00482         }
00483 
00484         return true;
00485     }
00486 }