[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/specials/ -> SpecialProtectedpages.php (source)

   1  <?php
   2  /**
   3   * Implements Special:Protectedpages
   4   *
   5   * This program is free software; you can redistribute it and/or modify
   6   * it under the terms of the GNU General Public License as published by
   7   * the Free Software Foundation; either version 2 of the License, or
   8   * (at your option) any later version.
   9   *
  10   * This program is distributed in the hope that it will be useful,
  11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13   * GNU General Public License for more details.
  14   *
  15   * You should have received a copy of the GNU General Public License along
  16   * with this program; if not, write to the Free Software Foundation, Inc.,
  17   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  18   * http://www.gnu.org/copyleft/gpl.html
  19   *
  20   * @file
  21   * @ingroup SpecialPage
  22   */
  23  
  24  /**
  25   * A special page that lists protected pages
  26   *
  27   * @ingroup SpecialPage
  28   */
  29  class SpecialProtectedpages extends SpecialPage {
  30      protected $IdLevel = 'level';
  31      protected $IdType = 'type';
  32  
  33  	public function __construct() {
  34          parent::__construct( 'Protectedpages' );
  35      }
  36  
  37  	public function execute( $par ) {
  38          $this->setHeaders();
  39          $this->outputHeader();
  40          $this->getOutput()->addModuleStyles( 'mediawiki.special' );
  41  
  42          // Purge expired entries on one in every 10 queries
  43          if ( !mt_rand( 0, 10 ) ) {
  44              Title::purgeExpiredRestrictions();
  45          }
  46  
  47          $request = $this->getRequest();
  48          $type = $request->getVal( $this->IdType );
  49          $level = $request->getVal( $this->IdLevel );
  50          $sizetype = $request->getVal( 'sizetype' );
  51          $size = $request->getIntOrNull( 'size' );
  52          $ns = $request->getIntOrNull( 'namespace' );
  53          $indefOnly = $request->getBool( 'indefonly' ) ? 1 : 0;
  54          $cascadeOnly = $request->getBool( 'cascadeonly' ) ? 1 : 0;
  55          $noRedirect = $request->getBool( 'noredirect' ) ? 1 : 0;
  56  
  57          $pager = new ProtectedPagesPager(
  58              $this,
  59              array(),
  60              $type,
  61              $level,
  62              $ns,
  63              $sizetype,
  64              $size,
  65              $indefOnly,
  66              $cascadeOnly,
  67              $noRedirect
  68          );
  69  
  70          $this->getOutput()->addHTML( $this->showOptions(
  71              $ns,
  72              $type,
  73              $level,
  74              $sizetype,
  75              $size,
  76              $indefOnly,
  77              $cascadeOnly,
  78              $noRedirect
  79          ) );
  80  
  81          if ( $pager->getNumRows() ) {
  82              $this->getOutput()->addParserOutputContent( $pager->getFullOutput() );
  83          } else {
  84              $this->getOutput()->addWikiMsg( 'protectedpagesempty' );
  85          }
  86      }
  87  
  88      /**
  89       * @param int $namespace
  90       * @param string $type Restriction type
  91       * @param string $level Restriction level
  92       * @param string $sizetype "min" or "max"
  93       * @param int $size
  94       * @param bool $indefOnly Only indefinite protection
  95       * @param bool $cascadeOnly Only cascading protection
  96       * @param bool $noRedirect Don't show redirects
  97       * @return string Input form
  98       */
  99  	protected function showOptions( $namespace, $type = 'edit', $level, $sizetype,
 100          $size, $indefOnly, $cascadeOnly, $noRedirect
 101      ) {
 102          $title = $this->getPageTitle();
 103  
 104          return Xml::openElement( 'form', array( 'method' => 'get', 'action' => wfScript() ) ) .
 105              Xml::openElement( 'fieldset' ) .
 106              Xml::element( 'legend', array(), $this->msg( 'protectedpages' )->text() ) .
 107              Html::hidden( 'title', $title->getPrefixedDBkey() ) . "\n" .
 108              $this->getNamespaceMenu( $namespace ) . "&#160;\n" .
 109              $this->getTypeMenu( $type ) . "&#160;\n" .
 110              $this->getLevelMenu( $level ) . "&#160;\n" .
 111              "<br /><span style='white-space: nowrap'>" .
 112              $this->getExpiryCheck( $indefOnly ) . "&#160;\n" .
 113              $this->getCascadeCheck( $cascadeOnly ) . "&#160;\n" .
 114              $this->getRedirectCheck( $noRedirect ) . "&#160;\n" .
 115              "</span><br /><span style='white-space: nowrap'>" .
 116              $this->getSizeLimit( $sizetype, $size ) . "&#160;\n" .
 117              "</span>" .
 118              "&#160;" . Xml::submitButton( $this->msg( 'allpagessubmit' )->text() ) . "\n" .
 119              Xml::closeElement( 'fieldset' ) .
 120              Xml::closeElement( 'form' );
 121      }
 122  
 123      /**
 124       * Prepare the namespace filter drop-down; standard namespace
 125       * selector, sans the MediaWiki namespace
 126       *
 127       * @param string|null $namespace Pre-select namespace
 128       * @return string
 129       */
 130  	protected function getNamespaceMenu( $namespace = null ) {
 131          return Html::rawElement( 'span', array( 'style' => 'white-space: nowrap;' ),
 132              Html::namespaceSelector(
 133                  array(
 134                      'selected' => $namespace,
 135                      'all' => '',
 136                      'label' => $this->msg( 'namespace' )->text()
 137                  ), array(
 138                      'name' => 'namespace',
 139                      'id' => 'namespace',
 140                      'class' => 'namespaceselector',
 141                  )
 142              )
 143          );
 144      }
 145  
 146      /**
 147       * @param bool $indefOnly
 148       * @return string Formatted HTML
 149       */
 150  	protected function getExpiryCheck( $indefOnly ) {
 151          return Xml::checkLabel(
 152              $this->msg( 'protectedpages-indef' )->text(),
 153              'indefonly',
 154              'indefonly',
 155              $indefOnly
 156          ) . "\n";
 157      }
 158  
 159      /**
 160       * @param bool $cascadeOnly
 161       * @return string Formatted HTML
 162       */
 163  	protected function getCascadeCheck( $cascadeOnly ) {
 164          return Xml::checkLabel(
 165              $this->msg( 'protectedpages-cascade' )->text(),
 166              'cascadeonly',
 167              'cascadeonly',
 168              $cascadeOnly
 169          ) . "\n";
 170      }
 171  
 172      /**
 173       * @param bool $noRedirect
 174       * @return string Formatted HTML
 175       */
 176  	protected function getRedirectCheck( $noRedirect ) {
 177          return Xml::checkLabel(
 178              $this->msg( 'protectedpages-noredirect' )->text(),
 179              'noredirect',
 180              'noredirect',
 181              $noRedirect
 182          ) . "\n";
 183      }
 184  
 185      /**
 186       * @param string $sizetype "min" or "max"
 187       * @param mixed $size
 188       * @return string Formatted HTML
 189       */
 190  	protected function getSizeLimit( $sizetype, $size ) {
 191          $max = $sizetype === 'max';
 192  
 193          return Xml::radioLabel(
 194              $this->msg( 'minimum-size' )->text(),
 195              'sizetype',
 196              'min',
 197              'wpmin',
 198              !$max
 199          ) .
 200              '&#160;' .
 201              Xml::radioLabel(
 202                  $this->msg( 'maximum-size' )->text(),
 203                  'sizetype',
 204                  'max',
 205                  'wpmax',
 206                  $max
 207              ) .
 208              '&#160;' .
 209              Xml::input( 'size', 9, $size, array( 'id' => 'wpsize' ) ) .
 210              '&#160;' .
 211              Xml::label( $this->msg( 'pagesize' )->text(), 'wpsize' );
 212      }
 213  
 214      /**
 215       * Creates the input label of the restriction type
 216       * @param string $pr_type Protection type
 217       * @return string Formatted HTML
 218       */
 219  	protected function getTypeMenu( $pr_type ) {
 220          $m = array(); // Temporary array
 221          $options = array();
 222  
 223          // First pass to load the log names
 224          foreach ( Title::getFilteredRestrictionTypes( true ) as $type ) {
 225              // Messages: restriction-edit, restriction-move, restriction-create, restriction-upload
 226              $text = $this->msg( "restriction-$type" )->text();
 227              $m[$text] = $type;
 228          }
 229  
 230          // Third pass generates sorted XHTML content
 231          foreach ( $m as $text => $type ) {
 232              $selected = ( $type == $pr_type );
 233              $options[] = Xml::option( $text, $type, $selected ) . "\n";
 234          }
 235  
 236          return "<span style='white-space: nowrap'>" .
 237              Xml::label( $this->msg( 'restriction-type' )->text(), $this->IdType ) . '&#160;' .
 238              Xml::tags( 'select',
 239                  array( 'id' => $this->IdType, 'name' => $this->IdType ),
 240                  implode( "\n", $options ) ) . "</span>";
 241      }
 242  
 243      /**
 244       * Creates the input label of the restriction level
 245       * @param string $pr_level Protection level
 246       * @return string Formatted HTML
 247       */
 248  	protected function getLevelMenu( $pr_level ) {
 249          // Temporary array
 250          $m = array( $this->msg( 'restriction-level-all' )->text() => 0 );
 251          $options = array();
 252  
 253          // First pass to load the log names
 254          foreach ( $this->getConfig()->get( 'RestrictionLevels' ) as $type ) {
 255              // Messages used can be 'restriction-level-sysop' and 'restriction-level-autoconfirmed'
 256              if ( $type != '' && $type != '*' ) {
 257                  $text = $this->msg( "restriction-level-$type" )->text();
 258                  $m[$text] = $type;
 259              }
 260          }
 261  
 262          // Third pass generates sorted XHTML content
 263          foreach ( $m as $text => $type ) {
 264              $selected = ( $type == $pr_level );
 265              $options[] = Xml::option( $text, $type, $selected );
 266          }
 267  
 268          return "<span style='white-space: nowrap'>" .
 269              Xml::label( $this->msg( 'restriction-level' )->text(), $this->IdLevel ) . ' ' .
 270              Xml::tags( 'select',
 271                  array( 'id' => $this->IdLevel, 'name' => $this->IdLevel ),
 272                  implode( "\n", $options ) ) . "</span>";
 273      }
 274  
 275  	protected function getGroupName() {
 276          return 'maintenance';
 277      }
 278  }
 279  
 280  /**
 281   * @todo document
 282   * @ingroup Pager
 283   */
 284  class ProtectedPagesPager extends TablePager {
 285      public $mForm, $mConds;
 286      private $type, $level, $namespace, $sizetype, $size, $indefonly, $cascadeonly, $noredirect;
 287  
 288  	function __construct( $form, $conds = array(), $type, $level, $namespace,
 289          $sizetype = '', $size = 0, $indefonly = false, $cascadeonly = false, $noredirect = false
 290      ) {
 291          $this->mForm = $form;
 292          $this->mConds = $conds;
 293          $this->type = ( $type ) ? $type : 'edit';
 294          $this->level = $level;
 295          $this->namespace = $namespace;
 296          $this->sizetype = $sizetype;
 297          $this->size = intval( $size );
 298          $this->indefonly = (bool)$indefonly;
 299          $this->cascadeonly = (bool)$cascadeonly;
 300          $this->noredirect = (bool)$noredirect;
 301          parent::__construct( $form->getContext() );
 302      }
 303  
 304  	function preprocessResults( $result ) {
 305          # Do a link batch query
 306          $lb = new LinkBatch;
 307          $userids = array();
 308  
 309          foreach ( $result as $row ) {
 310              $lb->add( $row->page_namespace, $row->page_title );
 311              // field is nullable, maybe null on old protections
 312              if ( $row->log_user !== null ) {
 313                  $userids[] = $row->log_user;
 314              }
 315          }
 316  
 317          // fill LinkBatch with user page and user talk
 318          if ( count( $userids ) ) {
 319              $userCache = UserCache::singleton();
 320              $userCache->doQuery( $userids, array(), __METHOD__ );
 321              foreach ( $userids as $userid ) {
 322                  $name = $userCache->getProp( $userid, 'name' );
 323                  if ( $name !== false ) {
 324                      $lb->add( NS_USER, $name );
 325                      $lb->add( NS_USER_TALK, $name );
 326                  }
 327              }
 328          }
 329  
 330          $lb->execute();
 331      }
 332  
 333  	function getFieldNames() {
 334          static $headers = null;
 335  
 336          if ( $headers == array() ) {
 337              $headers = array(
 338                  'log_timestamp' => 'protectedpages-timestamp',
 339                  'pr_page' => 'protectedpages-page',
 340                  'pr_expiry' => 'protectedpages-expiry',
 341                  'log_user' => 'protectedpages-performer',
 342                  'pr_params' => 'protectedpages-params',
 343                  'log_comment' => 'protectedpages-reason',
 344              );
 345              foreach ( $headers as $key => $val ) {
 346                  $headers[$key] = $this->msg( $val )->text();
 347              }
 348          }
 349  
 350          return $headers;
 351      }
 352  
 353      /**
 354       * @param string $field
 355       * @param string $value
 356       * @return string
 357       * @throws MWException
 358       */
 359  	function formatValue( $field, $value ) {
 360          /** @var $row object */
 361          $row = $this->mCurrentRow;
 362  
 363          $formatted = '';
 364  
 365          switch ( $field ) {
 366              case 'log_timestamp':
 367                  // when timestamp is null, this is a old protection row
 368                  if ( $value === null ) {
 369                      $formatted = Html::rawElement(
 370                          'span',
 371                          array( 'class' => 'mw-protectedpages-unknown' ),
 372                          $this->msg( 'protectedpages-unknown-timestamp' )->escaped()
 373                      );
 374                  } else {
 375                      $formatted = $this->getLanguage()->userTimeAndDate( $value, $this->getUser() );
 376                  }
 377                  break;
 378  
 379              case 'pr_page':
 380                  $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
 381                  if ( !$title ) {
 382                      $formatted = Html::element(
 383                          'span',
 384                          array( 'class' => 'mw-invalidtitle' ),
 385                          Linker::getInvalidTitleDescription(
 386                              $this->getContext(),
 387                              $row->page_namespace,
 388                              $row->page_title
 389                          )
 390                      );
 391                  } else {
 392                      $formatted = Linker::link( $title );
 393                  }
 394                  if ( !is_null( $row->page_len ) ) {
 395                      $formatted .= $this->getLanguage()->getDirMark() .
 396                          ' ' . Html::rawElement(
 397                          'span',
 398                          array( 'class' => 'mw-protectedpages-length' ),
 399                          Linker::formatRevisionSize( $row->page_len )
 400                      );
 401                  }
 402                  break;
 403  
 404              case 'pr_expiry':
 405                  $formatted = $this->getLanguage()->formatExpiry( $value, /* User preference timezone */true );
 406                  $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
 407                  if ( $this->getUser()->isAllowed( 'protect' ) && $title ) {
 408                      $changeProtection = Linker::linkKnown(
 409                          $title,
 410                          $this->msg( 'protect_change' )->escaped(),
 411                          array(),
 412                          array( 'action' => 'unprotect' )
 413                      );
 414                      $formatted .= ' ' . Html::rawElement(
 415                          'span',
 416                          array( 'class' => 'mw-protectedpages-actions' ),
 417                          $this->msg( 'parentheses' )->rawParams( $changeProtection )->escaped()
 418                      );
 419                  }
 420                  break;
 421  
 422              case 'log_user':
 423                  // when timestamp is null, this is a old protection row
 424                  if ( $row->log_timestamp === null ) {
 425                      $formatted = Html::rawElement(
 426                          'span',
 427                          array( 'class' => 'mw-protectedpages-unknown' ),
 428                          $this->msg( 'protectedpages-unknown-performer' )->escaped()
 429                      );
 430                  } else {
 431                      $username = UserCache::singleton()->getProp( $value, 'name' );
 432                      if ( LogEventsList::userCanBitfield(
 433                          $row->log_deleted,
 434                          LogPage::DELETED_USER,
 435                          $this->getUser()
 436                      ) ) {
 437                          if ( $username === false ) {
 438                              $formatted = htmlspecialchars( $value );
 439                          } else {
 440                              $formatted = Linker::userLink( $value, $username )
 441                                  . Linker::userToolLinks( $value, $username );
 442                          }
 443                      } else {
 444                          $formatted = $this->msg( 'rev-deleted-user' )->escaped();
 445                      }
 446                      if ( LogEventsList::isDeleted( $row, LogPage::DELETED_USER ) ) {
 447                          $formatted = '<span class="history-deleted">' . $formatted . '</span>';
 448                      }
 449                  }
 450                  break;
 451  
 452              case 'pr_params':
 453                  $params = array();
 454                  // Messages: restriction-level-sysop, restriction-level-autoconfirmed
 455                  $params[] = $this->msg( 'restriction-level-' . $row->pr_level )->escaped();
 456                  if ( $row->pr_cascade ) {
 457                      $params[] = $this->msg( 'protect-summary-cascade' )->text();
 458                  }
 459                  $formatted = $this->getLanguage()->commaList( $params );
 460                  break;
 461  
 462              case 'log_comment':
 463                  // when timestamp is null, this is an old protection row
 464                  if ( $row->log_timestamp === null ) {
 465                      $formatted = Html::rawElement(
 466                          'span',
 467                          array( 'class' => 'mw-protectedpages-unknown' ),
 468                          $this->msg( 'protectedpages-unknown-reason' )->escaped()
 469                      );
 470                  } else {
 471                      if ( LogEventsList::userCanBitfield(
 472                          $row->log_deleted,
 473                          LogPage::DELETED_COMMENT,
 474                          $this->getUser()
 475                      ) ) {
 476                          $formatted = Linker::formatComment( $value !== null ? $value : '' );
 477                      } else {
 478                          $formatted = $this->msg( 'rev-deleted-comment' )->escaped();
 479                      }
 480                      if ( LogEventsList::isDeleted( $row, LogPage::DELETED_COMMENT ) ) {
 481                          $formatted = '<span class="history-deleted">' . $formatted . '</span>';
 482                      }
 483                  }
 484                  break;
 485  
 486              default:
 487                  throw new MWException( "Unknown field '$field'" );
 488          }
 489  
 490          return $formatted;
 491      }
 492  
 493  	function getQueryInfo() {
 494          $conds = $this->mConds;
 495          $conds[] = 'pr_expiry > ' . $this->mDb->addQuotes( $this->mDb->timestamp() ) .
 496              'OR pr_expiry IS NULL';
 497          $conds[] = 'page_id=pr_page';
 498          $conds[] = 'pr_type=' . $this->mDb->addQuotes( $this->type );
 499  
 500          if ( $this->sizetype == 'min' ) {
 501              $conds[] = 'page_len>=' . $this->size;
 502          } elseif ( $this->sizetype == 'max' ) {
 503              $conds[] = 'page_len<=' . $this->size;
 504          }
 505  
 506          if ( $this->indefonly ) {
 507              $infinity = $this->mDb->addQuotes( $this->mDb->getInfinity() );
 508              $conds[] = "pr_expiry = $infinity OR pr_expiry IS NULL";
 509          }
 510          if ( $this->cascadeonly ) {
 511              $conds[] = 'pr_cascade = 1';
 512          }
 513          if ( $this->noredirect ) {
 514              $conds[] = 'page_is_redirect = 0';
 515          }
 516  
 517          if ( $this->level ) {
 518              $conds[] = 'pr_level=' . $this->mDb->addQuotes( $this->level );
 519          }
 520          if ( !is_null( $this->namespace ) ) {
 521              $conds[] = 'page_namespace=' . $this->mDb->addQuotes( $this->namespace );
 522          }
 523  
 524          return array(
 525              'tables' => array( 'page', 'page_restrictions', 'log_search', 'logging' ),
 526              'fields' => array(
 527                  'pr_id',
 528                  'page_namespace',
 529                  'page_title',
 530                  'page_len',
 531                  'pr_type',
 532                  'pr_level',
 533                  'pr_expiry',
 534                  'pr_cascade',
 535                  'log_timestamp',
 536                  'log_user',
 537                  'log_comment',
 538                  'log_deleted',
 539              ),
 540              'conds' => $conds,
 541              'join_conds' => array(
 542                  'log_search' => array(
 543                      'LEFT JOIN', array(
 544                          'ls_field' => 'pr_id', 'ls_value = pr_id'
 545                      )
 546                  ),
 547                  'logging' => array(
 548                      'LEFT JOIN', array(
 549                          'ls_log_id = log_id'
 550                      )
 551                  )
 552              )
 553          );
 554      }
 555  
 556  	public function getTableClass() {
 557          return parent::getTableClass() . ' mw-protectedpages';
 558      }
 559  
 560  	function getIndexField() {
 561          return 'pr_id';
 562      }
 563  
 564  	function getDefaultSort() {
 565          return 'pr_id';
 566      }
 567  
 568  	function isFieldSortable( $field ) {
 569          // no index for sorting exists
 570          return false;
 571      }
 572  }


Generated: Fri Nov 28 14:03:12 2014 Cross-referenced by PHPXref 0.7.1