MediaWiki  REL1_23
SpecialProtectedpages.php
Go to the documentation of this file.
00001 <?php
00029 class SpecialProtectedpages extends SpecialPage {
00030 
00031     protected $IdLevel = 'level';
00032     protected $IdType = 'type';
00033 
00034     public function __construct() {
00035         parent::__construct( 'Protectedpages' );
00036     }
00037 
00038     public function execute( $par ) {
00039         $this->setHeaders();
00040         $this->outputHeader();
00041         $this->getOutput()->addModuleStyles( 'mediawiki.special' );
00042 
00043         // Purge expired entries on one in every 10 queries
00044         if ( !mt_rand( 0, 10 ) ) {
00045             Title::purgeExpiredRestrictions();
00046         }
00047 
00048         $request = $this->getRequest();
00049         $type = $request->getVal( $this->IdType );
00050         $level = $request->getVal( $this->IdLevel );
00051         $sizetype = $request->getVal( 'sizetype' );
00052         $size = $request->getIntOrNull( 'size' );
00053         $ns = $request->getIntOrNull( 'namespace' );
00054         $indefOnly = $request->getBool( 'indefonly' ) ? 1 : 0;
00055         $cascadeOnly = $request->getBool( 'cascadeonly' ) ? 1 : 0;
00056         $noRedirect = $request->getBool( 'noredirect' ) ? 1 : 0;
00057 
00058         $pager = new ProtectedPagesPager(
00059             $this,
00060             array(),
00061             $type,
00062             $level,
00063             $ns,
00064             $sizetype,
00065             $size,
00066             $indefOnly,
00067             $cascadeOnly,
00068             $noRedirect
00069         );
00070 
00071         $this->getOutput()->addHTML( $this->showOptions(
00072             $ns,
00073             $type,
00074             $level,
00075             $sizetype,
00076             $size,
00077             $indefOnly,
00078             $cascadeOnly,
00079             $noRedirect
00080         ) );
00081 
00082         if ( $pager->getNumRows() ) {
00083             $this->getOutput()->addHTML(
00084                 $pager->getNavigationBar() .
00085                     $pager->getBody() .
00086                     $pager->getNavigationBar()
00087             );
00088         } else {
00089             $this->getOutput()->addWikiMsg( 'protectedpagesempty' );
00090         }
00091     }
00092 
00104     protected function showOptions( $namespace, $type = 'edit', $level, $sizetype,
00105         $size, $indefOnly, $cascadeOnly, $noRedirect
00106     ) {
00107         global $wgScript;
00108 
00109         $title = $this->getPageTitle();
00110 
00111         return Xml::openElement( 'form', array( 'method' => 'get', 'action' => $wgScript ) ) .
00112             Xml::openElement( 'fieldset' ) .
00113             Xml::element( 'legend', array(), $this->msg( 'protectedpages' )->text() ) .
00114             Html::hidden( 'title', $title->getPrefixedDBkey() ) . "\n" .
00115             $this->getNamespaceMenu( $namespace ) . "&#160;\n" .
00116             $this->getTypeMenu( $type ) . "&#160;\n" .
00117             $this->getLevelMenu( $level ) . "&#160;\n" .
00118             "<br /><span style='white-space: nowrap'>" .
00119             $this->getExpiryCheck( $indefOnly ) . "&#160;\n" .
00120             $this->getCascadeCheck( $cascadeOnly ) . "&#160;\n" .
00121             $this->getRedirectCheck( $noRedirect ) . "&#160;\n" .
00122             "</span><br /><span style='white-space: nowrap'>" .
00123             $this->getSizeLimit( $sizetype, $size ) . "&#160;\n" .
00124             "</span>" .
00125             "&#160;" . Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "\n" .
00126             Xml::closeElement( 'fieldset' ) .
00127             Xml::closeElement( 'form' );
00128     }
00129 
00137     protected function getNamespaceMenu( $namespace = null ) {
00138         return Html::rawElement( 'span', array( 'style' => 'white-space: nowrap;' ),
00139             Html::namespaceSelector(
00140                 array(
00141                     'selected' => $namespace,
00142                     'all' => '',
00143                     'label' => $this->msg( 'namespace' )->text()
00144                 ), array(
00145                     'name' => 'namespace',
00146                     'id' => 'namespace',
00147                     'class' => 'namespaceselector',
00148                 )
00149             )
00150         );
00151     }
00152 
00157     protected function getExpiryCheck( $indefOnly ) {
00158         return Xml::checkLabel(
00159             $this->msg( 'protectedpages-indef' )->text(),
00160             'indefonly',
00161             'indefonly',
00162             $indefOnly
00163         ) . "\n";
00164     }
00165 
00170     protected function getCascadeCheck( $cascadeOnly ) {
00171         return Xml::checkLabel(
00172             $this->msg( 'protectedpages-cascade' )->text(),
00173             'cascadeonly',
00174             'cascadeonly',
00175             $cascadeOnly
00176         ) . "\n";
00177     }
00178 
00183     protected function getRedirectCheck( $noRedirect ) {
00184         return Xml::checkLabel(
00185             $this->msg( 'protectedpages-noredirect' )->text(),
00186             'noredirect',
00187             'noredirect',
00188             $noRedirect
00189         ) . "\n";
00190     }
00191 
00197     protected function getSizeLimit( $sizetype, $size ) {
00198         $max = $sizetype === 'max';
00199 
00200         return Xml::radioLabel(
00201             $this->msg( 'minimum-size' )->text(),
00202             'sizetype',
00203             'min',
00204             'wpmin',
00205             !$max
00206         ) .
00207             '&#160;' .
00208             Xml::radioLabel(
00209                 $this->msg( 'maximum-size' )->text(),
00210                 'sizetype',
00211                 'max',
00212                 'wpmax',
00213                 $max
00214             ) .
00215             '&#160;' .
00216             Xml::input( 'size', 9, $size, array( 'id' => 'wpsize' ) ) .
00217             '&#160;' .
00218             Xml::label( $this->msg( 'pagesize' )->text(), 'wpsize' );
00219     }
00220 
00226     protected function getTypeMenu( $pr_type ) {
00227         $m = array(); // Temporary array
00228         $options = array();
00229 
00230         // First pass to load the log names
00231         foreach ( Title::getFilteredRestrictionTypes( true ) as $type ) {
00232             // Messages: restriction-edit, restriction-move, restriction-create, restriction-upload
00233             $text = $this->msg( "restriction-$type" )->text();
00234             $m[$text] = $type;
00235         }
00236 
00237         // Third pass generates sorted XHTML content
00238         foreach ( $m as $text => $type ) {
00239             $selected = ( $type == $pr_type );
00240             $options[] = Xml::option( $text, $type, $selected ) . "\n";
00241         }
00242 
00243         return "<span style='white-space: nowrap'>" .
00244             Xml::label( $this->msg( 'restriction-type' )->text(), $this->IdType ) . '&#160;' .
00245             Xml::tags( 'select',
00246                 array( 'id' => $this->IdType, 'name' => $this->IdType ),
00247                 implode( "\n", $options ) ) . "</span>";
00248     }
00249 
00255     protected function getLevelMenu( $pr_level ) {
00256         global $wgRestrictionLevels;
00257 
00258         // Temporary array
00259         $m = array( $this->msg( 'restriction-level-all' )->text() => 0 );
00260         $options = array();
00261 
00262         // First pass to load the log names
00263         foreach ( $wgRestrictionLevels as $type ) {
00264             // Messages used can be 'restriction-level-sysop' and 'restriction-level-autoconfirmed'
00265             if ( $type != '' && $type != '*' ) {
00266                 $text = $this->msg( "restriction-level-$type" )->text();
00267                 $m[$text] = $type;
00268             }
00269         }
00270 
00271         // Third pass generates sorted XHTML content
00272         foreach ( $m as $text => $type ) {
00273             $selected = ( $type == $pr_level );
00274             $options[] = Xml::option( $text, $type, $selected );
00275         }
00276 
00277         return "<span style='white-space: nowrap'>" .
00278             Xml::label( $this->msg( 'restriction-level' )->text(), $this->IdLevel ) . ' ' .
00279             Xml::tags( 'select',
00280                 array( 'id' => $this->IdLevel, 'name' => $this->IdLevel ),
00281                 implode( "\n", $options ) ) . "</span>";
00282     }
00283 
00284     protected function getGroupName() {
00285         return 'maintenance';
00286     }
00287 }
00288 
00293 class ProtectedPagesPager extends TablePager {
00294     public $mForm, $mConds;
00295     private $type, $level, $namespace, $sizetype, $size, $indefonly, $cascadeonly, $noredirect;
00296 
00297     function __construct( $form, $conds = array(), $type, $level, $namespace,
00298         $sizetype = '', $size = 0, $indefonly = false, $cascadeonly = false, $noredirect = false
00299     ) {
00300         $this->mForm = $form;
00301         $this->mConds = $conds;
00302         $this->type = ( $type ) ? $type : 'edit';
00303         $this->level = $level;
00304         $this->namespace = $namespace;
00305         $this->sizetype = $sizetype;
00306         $this->size = intval( $size );
00307         $this->indefonly = (bool)$indefonly;
00308         $this->cascadeonly = (bool)$cascadeonly;
00309         $this->noredirect = (bool)$noredirect;
00310         parent::__construct( $form->getContext() );
00311     }
00312 
00313     function preprocessResults( $result ) {
00314         # Do a link batch query
00315         $lb = new LinkBatch;
00316         $userids = array();
00317 
00318         foreach ( $result as $row ) {
00319             $lb->add( $row->page_namespace, $row->page_title );
00320             // field is nullable, maybe null on old protections
00321             if ( $row->log_user !== null ) {
00322                 $userids[] = $row->log_user;
00323             }
00324         }
00325 
00326         // fill LinkBatch with user page and user talk
00327         if ( count( $userids ) ) {
00328             $userCache = UserCache::singleton();
00329             $userCache->doQuery( $userids, array(), __METHOD__ );
00330             foreach ( $userids as $userid ) {
00331                 $name = $userCache->getProp( $userid, 'name' );
00332                 if ( $name !== false ) {
00333                     $lb->add( NS_USER, $name );
00334                     $lb->add( NS_USER_TALK, $name );
00335                 }
00336             }
00337         }
00338 
00339         $lb->execute();
00340     }
00341 
00342     function getFieldNames() {
00343         static $headers = null;
00344 
00345         if ( $headers == array() ) {
00346             $headers = array(
00347                 'log_timestamp' => 'protectedpages-timestamp',
00348                 'pr_page' => 'protectedpages-page',
00349                 'pr_expiry' => 'protectedpages-expiry',
00350                 'log_user' => 'protectedpages-performer',
00351                 'pr_params' => 'protectedpages-params',
00352                 'log_comment' => 'protectedpages-reason',
00353             );
00354             foreach ( $headers as $key => $val ) {
00355                 $headers[$key] = $this->msg( $val )->text();
00356             }
00357         }
00358 
00359         return $headers;
00360     }
00361 
00368     function formatValue( $field, $value ) {
00370         $row = $this->mCurrentRow;
00371 
00372         $formatted = '';
00373 
00374         switch ( $field ) {
00375             case 'log_timestamp':
00376                 // when timestamp is null, this is a old protection row
00377                 if ( $value === null ) {
00378                     $formatted = Html::rawElement(
00379                         'span',
00380                         array( 'class' => 'mw-protectedpages-unknown' ),
00381                         $this->msg( 'protectedpages-unknown-timestamp' )->escaped()
00382                     );
00383                 } else {
00384                     $formatted = $this->getLanguage()->userTimeAndDate( $value, $this->getUser() );
00385                 }
00386                 break;
00387 
00388             case 'pr_page':
00389                 $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
00390                 if ( !$title ) {
00391                     $formatted = Html::element(
00392                         'span',
00393                         array( 'class' => 'mw-invalidtitle' ),
00394                         Linker::getInvalidTitleDescription(
00395                             $this->getContext(),
00396                             $row->page_namespace,
00397                             $row->page_title
00398                         )
00399                     );
00400                 } else {
00401                     $formatted = Linker::link( $title );
00402                 }
00403                 if ( !is_null( $row->page_len ) ) {
00404                     $formatted .= $this->getLanguage()->getDirMark() .
00405                         ' ' . Html::rawElement(
00406                         'span',
00407                         array( 'class' => 'mw-protectedpages-length' ),
00408                         Linker::formatRevisionSize( $row->page_len )
00409                     );
00410                 }
00411                 break;
00412 
00413             case 'pr_expiry':
00414                 $formatted = $this->getLanguage()->formatExpiry( $value, /* User preference timezone */true );
00415                 $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
00416                 if ( $this->getUser()->isAllowed( 'protect' ) && $title ) {
00417                     $changeProtection = Linker::linkKnown(
00418                         $title,
00419                         $this->msg( 'protect_change' )->escaped(),
00420                         array(),
00421                         array( 'action' => 'unprotect' )
00422                     );
00423                     $formatted .= ' ' . Html::rawElement(
00424                         'span',
00425                         array( 'class' => 'mw-protectedpages-actions' ),
00426                         $this->msg( 'parentheses' )->rawParams( $changeProtection )->escaped()
00427                     );
00428                 }
00429                 break;
00430 
00431             case 'log_user':
00432                 // when timestamp is null, this is a old protection row
00433                 if ( $row->log_timestamp === null ) {
00434                     $formatted = Html::rawElement(
00435                         'span',
00436                         array( 'class' => 'mw-protectedpages-unknown' ),
00437                         $this->msg( 'protectedpages-unknown-performer' )->escaped()
00438                     );
00439                 } else {
00440                     $username = UserCache::singleton()->getProp( $value, 'name' );
00441                     if ( LogEventsList::userCanBitfield( $row->log_deleted, LogPage::DELETED_USER, $this->getUser() ) ) {
00442                         if ( $username === false ) {
00443                             $formatted = htmlspecialchars( $value );
00444                         } else {
00445                             $formatted = Linker::userLink( $value, $username )
00446                                 . Linker::userToolLinks( $value, $username );
00447                         }
00448                     } else {
00449                         $formatted = $this->msg( 'rev-deleted-user' )->escaped();
00450                     }
00451                     if ( LogEventsList::isDeleted( $row, LogPage::DELETED_USER ) ) {
00452                         $formatted = '<span class="history-deleted">' . $formatted . '</span>';
00453                     }
00454                 }
00455                 break;
00456 
00457             case 'pr_params':
00458                 $params = array();
00459                 // Messages: restriction-level-sysop, restriction-level-autoconfirmed
00460                 $params[] = $this->msg( 'restriction-level-' . $row->pr_level )->escaped();
00461                 if ( $row->pr_cascade ) {
00462                     $params[] = $this->msg( 'protect-summary-cascade' )->text();
00463                 }
00464                 $formatted = $this->getLanguage()->commaList( $params );
00465                 break;
00466 
00467             case 'log_comment':
00468                 // when timestamp is null, this is an old protection row
00469                 if ( $row->log_timestamp === null ) {
00470                     $formatted = Html::rawElement(
00471                         'span',
00472                         array( 'class' => 'mw-protectedpages-unknown' ),
00473                         $this->msg( 'protectedpages-unknown-reason' )->escaped()
00474                     );
00475                 } else {
00476                     if ( LogEventsList::userCanBitfield( $row->log_deleted, LogPage::DELETED_COMMENT, $this->getUser() ) ) {
00477                         $formatted = Linker::formatComment( $value !== null ? $value : '' );
00478                     } else {
00479                         $formatted = $this->msg( 'rev-deleted-comment' )->escaped();
00480                     }
00481                     if ( LogEventsList::isDeleted( $row, LogPage::DELETED_COMMENT ) ) {
00482                         $formatted = '<span class="history-deleted">' . $formatted . '</span>';
00483                     }
00484                 }
00485                 break;
00486 
00487             default:
00488                 throw new MWException( "Unknown field '$field'" );
00489         }
00490 
00491         return $formatted;
00492     }
00493 
00494     function getQueryInfo() {
00495         $conds = $this->mConds;
00496         $conds[] = 'pr_expiry > ' . $this->mDb->addQuotes( $this->mDb->timestamp() ) .
00497             'OR pr_expiry IS NULL';
00498         $conds[] = 'page_id=pr_page';
00499         $conds[] = 'pr_type=' . $this->mDb->addQuotes( $this->type );
00500 
00501         if ( $this->sizetype == 'min' ) {
00502             $conds[] = 'page_len>=' . $this->size;
00503         } elseif ( $this->sizetype == 'max' ) {
00504             $conds[] = 'page_len<=' . $this->size;
00505         }
00506 
00507         if ( $this->indefonly ) {
00508             $infinity = $this->mDb->addQuotes( $this->mDb->getInfinity() );
00509             $conds[] = "pr_expiry = $infinity OR pr_expiry IS NULL";
00510         }
00511         if ( $this->cascadeonly ) {
00512             $conds[] = 'pr_cascade = 1';
00513         }
00514         if ( $this->noredirect ) {
00515             $conds[] = 'page_is_redirect = 0';
00516         }
00517 
00518         if ( $this->level ) {
00519             $conds[] = 'pr_level=' . $this->mDb->addQuotes( $this->level );
00520         }
00521         if ( !is_null( $this->namespace ) ) {
00522             $conds[] = 'page_namespace=' . $this->mDb->addQuotes( $this->namespace );
00523         }
00524 
00525         return array(
00526             'tables' => array( 'page', 'page_restrictions', 'log_search', 'logging' ),
00527             'fields' => array(
00528                 'pr_id',
00529                 'page_namespace',
00530                 'page_title',
00531                 'page_len',
00532                 'pr_type',
00533                 'pr_level',
00534                 'pr_expiry',
00535                 'pr_cascade',
00536                 'log_timestamp',
00537                 'log_user',
00538                 'log_comment',
00539                 'log_deleted',
00540             ),
00541             'conds' => $conds,
00542             'join_conds' => array(
00543                 'log_search' => array(
00544                     'LEFT JOIN', array(
00545                         'ls_field' => 'pr_id', 'ls_value = pr_id'
00546                     )
00547                 ),
00548                 'logging' => array(
00549                     'LEFT JOIN', array(
00550                         'ls_log_id = log_id'
00551                     )
00552                 )
00553             )
00554         );
00555     }
00556 
00557     public function getTableClass() {
00558         return 'TablePager mw-protectedpages';
00559     }
00560 
00561     function getIndexField() {
00562         return 'pr_id';
00563     }
00564 
00565     function getDefaultSort() {
00566         return 'pr_id';
00567     }
00568 
00569     function isFieldSortable( $field ) {
00570         // no index for sorting exists
00571         return false;
00572     }
00573 }