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