MediaWiki
REL1_23
|
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 ) . " \n" . 00116 $this->getTypeMenu( $type ) . " \n" . 00117 $this->getLevelMenu( $level ) . " \n" . 00118 "<br /><span style='white-space: nowrap'>" . 00119 $this->getExpiryCheck( $indefOnly ) . " \n" . 00120 $this->getCascadeCheck( $cascadeOnly ) . " \n" . 00121 $this->getRedirectCheck( $noRedirect ) . " \n" . 00122 "</span><br /><span style='white-space: nowrap'>" . 00123 $this->getSizeLimit( $sizetype, $size ) . " \n" . 00124 "</span>" . 00125 " " . 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 ' ' . 00208 Xml::radioLabel( 00209 $this->msg( 'maximum-size' )->text(), 00210 'sizetype', 00211 'max', 00212 'wpmax', 00213 $max 00214 ) . 00215 ' ' . 00216 Xml::input( 'size', 9, $size, array( 'id' => 'wpsize' ) ) . 00217 ' ' . 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 ) . ' ' . 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 }