[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/ -> ProtectionForm.php (source)

   1  <?php
   2  /**
   3   * Page protection
   4   *
   5   * Copyright © 2005 Brion Vibber <[email protected]>
   6   * https://www.mediawiki.org/
   7   *
   8   * This program is free software; you can redistribute it and/or modify
   9   * it under the terms of the GNU General Public License as published by
  10   * the Free Software Foundation; either version 2 of the License, or
  11   * (at your option) any later version.
  12   *
  13   * This program is distributed in the hope that it will be useful,
  14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16   * GNU General Public License for more details.
  17   *
  18   * You should have received a copy of the GNU General Public License along
  19   * with this program; if not, write to the Free Software Foundation, Inc.,
  20   * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  21   * http://www.gnu.org/copyleft/gpl.html
  22   *
  23   * @file
  24   */
  25  
  26  /**
  27   * Handles the page protection UI and backend
  28   */
  29  class ProtectionForm {
  30      /** @var array A map of action to restriction level, from request or default */
  31      protected $mRestrictions = array();
  32  
  33      /** @var string The custom/additional protection reason */
  34      protected $mReason = '';
  35  
  36      /** @var string The reason selected from the list, blank for other/additional */
  37      protected $mReasonSelection = '';
  38  
  39      /** @var bool True if the restrictions are cascading, from request or existing protection */
  40      protected $mCascade = false;
  41  
  42      /** @var array Map of action to "other" expiry time. Used in preference to mExpirySelection. */
  43      protected $mExpiry = array();
  44  
  45      /**
  46       * @var array Map of action to value selected in expiry drop-down list.
  47       * Will be set to 'othertime' whenever mExpiry is set.
  48       */
  49      protected $mExpirySelection = array();
  50  
  51      /** @var array Permissions errors for the protect action */
  52      protected $mPermErrors = array();
  53  
  54      /** @var array Types (i.e. actions) for which levels can be selected */
  55      protected $mApplicableTypes = array();
  56  
  57      /** @var array Map of action to the expiry time of the existing protection */
  58      protected $mExistingExpiry = array();
  59  
  60      /** @var IContextSource */
  61      private $mContext;
  62  
  63  	function __construct( Article $article ) {
  64          // Set instance variables.
  65          $this->mArticle = $article;
  66          $this->mTitle = $article->getTitle();
  67          $this->mApplicableTypes = $this->mTitle->getRestrictionTypes();
  68          $this->mContext = $article->getContext();
  69  
  70          // Check if the form should be disabled.
  71          // If it is, the form will be available in read-only to show levels.
  72          $this->mPermErrors = $this->mTitle->getUserPermissionsErrors(
  73              'protect', $this->mContext->getUser()
  74          );
  75          if ( wfReadOnly() ) {
  76              $this->mPermErrors[] = array( 'readonlytext', wfReadOnlyReason() );
  77          }
  78          $this->disabled = $this->mPermErrors != array();
  79          $this->disabledAttrib = $this->disabled
  80              ? array( 'disabled' => 'disabled' )
  81              : array();
  82  
  83          $this->loadData();
  84      }
  85  
  86      /**
  87       * Loads the current state of protection into the object.
  88       */
  89  	function loadData() {
  90          $levels = MWNamespace::getRestrictionLevels(
  91              $this->mTitle->getNamespace(), $this->mContext->getUser()
  92          );
  93          $this->mCascade = $this->mTitle->areRestrictionsCascading();
  94  
  95          $request = $this->mContext->getRequest();
  96          $this->mReason = $request->getText( 'mwProtect-reason' );
  97          $this->mReasonSelection = $request->getText( 'wpProtectReasonSelection' );
  98          $this->mCascade = $request->getBool( 'mwProtect-cascade', $this->mCascade );
  99  
 100          foreach ( $this->mApplicableTypes as $action ) {
 101              // @todo FIXME: This form currently requires individual selections,
 102              // but the db allows multiples separated by commas.
 103  
 104              // Pull the actual restriction from the DB
 105              $this->mRestrictions[$action] = implode( '', $this->mTitle->getRestrictions( $action ) );
 106  
 107              if ( !$this->mRestrictions[$action] ) {
 108                  // No existing expiry
 109                  $existingExpiry = '';
 110              } else {
 111                  $existingExpiry = $this->mTitle->getRestrictionExpiry( $action );
 112              }
 113              $this->mExistingExpiry[$action] = $existingExpiry;
 114  
 115              $requestExpiry = $request->getText( "mwProtect-expiry-$action" );
 116              $requestExpirySelection = $request->getVal( "wpProtectExpirySelection-$action" );
 117  
 118              if ( $requestExpiry ) {
 119                  // Custom expiry takes precedence
 120                  $this->mExpiry[$action] = $requestExpiry;
 121                  $this->mExpirySelection[$action] = 'othertime';
 122              } elseif ( $requestExpirySelection ) {
 123                  // Expiry selected from list
 124                  $this->mExpiry[$action] = '';
 125                  $this->mExpirySelection[$action] = $requestExpirySelection;
 126              } elseif ( $existingExpiry ) {
 127                  // Use existing expiry in its own list item
 128                  $this->mExpiry[$action] = '';
 129                  $this->mExpirySelection[$action] = $existingExpiry;
 130              } else {
 131                  // Catches 'infinity' - Existing expiry is infinite, use "infinite" in drop-down
 132                  // Final default: infinite
 133                  $this->mExpiry[$action] = '';
 134                  $this->mExpirySelection[$action] = 'infinite';
 135              }
 136  
 137              $val = $request->getVal( "mwProtect-level-$action" );
 138              if ( isset( $val ) && in_array( $val, $levels ) ) {
 139                  $this->mRestrictions[$action] = $val;
 140              }
 141          }
 142      }
 143  
 144      /**
 145       * Get the expiry time for a given action, by combining the relevant inputs.
 146       *
 147       * @param string $action
 148       *
 149       * @return string 14-char timestamp or "infinity", or false if the input was invalid
 150       */
 151  	function getExpiry( $action ) {
 152          if ( $this->mExpirySelection[$action] == 'existing' ) {
 153              return $this->mExistingExpiry[$action];
 154          } elseif ( $this->mExpirySelection[$action] == 'othertime' ) {
 155              $value = $this->mExpiry[$action];
 156          } else {
 157              $value = $this->mExpirySelection[$action];
 158          }
 159          if ( $value == 'infinite' || $value == 'indefinite' || $value == 'infinity' ) {
 160              $time = wfGetDB( DB_SLAVE )->getInfinity();
 161          } else {
 162              $unix = strtotime( $value );
 163  
 164              if ( !$unix || $unix === -1 ) {
 165                  return false;
 166              }
 167  
 168              // @todo FIXME: Non-qualified absolute times are not in users specified timezone
 169              // and there isn't notice about it in the ui
 170              $time = wfTimestamp( TS_MW, $unix );
 171          }
 172          return $time;
 173      }
 174  
 175      /**
 176       * Main entry point for action=protect and action=unprotect
 177       */
 178  	function execute() {
 179          if ( MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace() ) === array( '' ) ) {
 180              throw new ErrorPageError( 'protect-badnamespace-title', 'protect-badnamespace-text' );
 181          }
 182  
 183          if ( $this->mContext->getRequest()->wasPosted() ) {
 184              if ( $this->save() ) {
 185                  $q = $this->mArticle->isRedirect() ? 'redirect=no' : '';
 186                  $this->mContext->getOutput()->redirect( $this->mTitle->getFullURL( $q ) );
 187              }
 188          } else {
 189              $this->show();
 190          }
 191      }
 192  
 193      /**
 194       * Show the input form with optional error message
 195       *
 196       * @param string $err Error message or null if there's no error
 197       */
 198  	function show( $err = null ) {
 199          $out = $this->mContext->getOutput();
 200          $out->setRobotPolicy( 'noindex,nofollow' );
 201          $out->addBacklinkSubtitle( $this->mTitle );
 202  
 203          if ( is_array( $err ) ) {
 204              $out->wrapWikiMsg( "<p class='error'>\n$1\n</p>\n", $err );
 205          } elseif ( is_string( $err ) ) {
 206              $out->addHTML( "<p class='error'>{$err}</p>\n" );
 207          }
 208  
 209          if ( $this->mTitle->getRestrictionTypes() === array() ) {
 210              // No restriction types available for the current title
 211              // this might happen if an extension alters the available types
 212              $out->setPageTitle( wfMessage(
 213                  'protect-norestrictiontypes-title',
 214                  $this->mTitle->getPrefixedText()
 215              ) );
 216              $out->addWikiText( wfMessage( 'protect-norestrictiontypes-text' )->text() );
 217  
 218              // Show the log in case protection was possible once
 219              $this->showLogExtract( $out );
 220              // return as there isn't anything else we can do
 221              return;
 222          }
 223  
 224          list( $cascadeSources, /* $restrictions */ ) = $this->mTitle->getCascadeProtectionSources();
 225          if ( $cascadeSources && count( $cascadeSources ) > 0 ) {
 226              $titles = '';
 227  
 228              foreach ( $cascadeSources as $title ) {
 229                  $titles .= '* [[:' . $title->getPrefixedText() . "]]\n";
 230              }
 231  
 232              /** @todo FIXME: i18n issue, should use formatted number. */
 233              $out->wrapWikiMsg(
 234                  "<div id=\"mw-protect-cascadeon\">\n$1\n" . $titles . "</div>",
 235                  array( 'protect-cascadeon', count( $cascadeSources ) )
 236              );
 237          }
 238  
 239          # Show an appropriate message if the user isn't allowed or able to change
 240          # the protection settings at this time
 241          if ( $this->disabled ) {
 242              $out->setPageTitle(
 243                  wfMessage( 'protect-title-notallowed',
 244                      $this->mTitle->getPrefixedText() )
 245              );
 246              $out->addWikiText( $out->formatPermissionsErrorMessage( $this->mPermErrors, 'protect' ) );
 247          } else {
 248              $out->setPageTitle( wfMessage( 'protect-title', $this->mTitle->getPrefixedText() ) );
 249              $out->addWikiMsg( 'protect-text',
 250                  wfEscapeWikiText( $this->mTitle->getPrefixedText() ) );
 251          }
 252  
 253          $out->addHTML( $this->buildForm() );
 254          $this->showLogExtract( $out );
 255      }
 256  
 257      /**
 258       * Save submitted protection form
 259       *
 260       * @return bool Success
 261       */
 262  	function save() {
 263          # Permission check!
 264          if ( $this->disabled ) {
 265              $this->show();
 266              return false;
 267          }
 268  
 269          $request = $this->mContext->getRequest();
 270          $user = $this->mContext->getUser();
 271          $out = $this->mContext->getOutput();
 272          $token = $request->getVal( 'wpEditToken' );
 273          if ( !$user->matchEditToken( $token, array( 'protect', $this->mTitle->getPrefixedDBkey() ) ) ) {
 274              $this->show( array( 'sessionfailure' ) );
 275              return false;
 276          }
 277  
 278          # Create reason string. Use list and/or custom string.
 279          $reasonstr = $this->mReasonSelection;
 280          if ( $reasonstr != 'other' && $this->mReason != '' ) {
 281              // Entry from drop down menu + additional comment
 282              $reasonstr .= wfMessage( 'colon-separator' )->text() . $this->mReason;
 283          } elseif ( $reasonstr == 'other' ) {
 284              $reasonstr = $this->mReason;
 285          }
 286          $expiry = array();
 287          foreach ( $this->mApplicableTypes as $action ) {
 288              $expiry[$action] = $this->getExpiry( $action );
 289              if ( empty( $this->mRestrictions[$action] ) ) {
 290                  continue; // unprotected
 291              }
 292              if ( !$expiry[$action] ) {
 293                  $this->show( array( 'protect_expiry_invalid' ) );
 294                  return false;
 295              }
 296              if ( $expiry[$action] < wfTimestampNow() ) {
 297                  $this->show( array( 'protect_expiry_old' ) );
 298                  return false;
 299              }
 300          }
 301  
 302          $this->mCascade = $request->getBool( 'mwProtect-cascade' );
 303  
 304          $status = $this->mArticle->doUpdateRestrictions(
 305              $this->mRestrictions,
 306              $expiry,
 307              $this->mCascade,
 308              $reasonstr,
 309              $user
 310          );
 311  
 312          if ( !$status->isOK() ) {
 313              $this->show( $out->parseInline( $status->getWikiText() ) );
 314              return false;
 315          }
 316  
 317          /**
 318           * Give extensions a change to handle added form items
 319           *
 320           * @since 1.19 you can (and you should) return false to abort saving;
 321           *             you can also return an array of message name and its parameters
 322           */
 323          $errorMsg = '';
 324          if ( !wfRunHooks( 'ProtectionForm::save', array( $this->mArticle, &$errorMsg, $reasonstr ) ) ) {
 325              if ( $errorMsg == '' ) {
 326                  $errorMsg = array( 'hookaborted' );
 327              }
 328          }
 329          if ( $errorMsg != '' ) {
 330              $this->show( $errorMsg );
 331              return false;
 332          }
 333  
 334          WatchAction::doWatchOrUnwatch( $request->getCheck( 'mwProtectWatch' ), $this->mTitle, $user );
 335  
 336          return true;
 337      }
 338  
 339      /**
 340       * Build the input form
 341       *
 342       * @return string HTML form
 343       */
 344  	function buildForm() {
 345          $user = $this->mContext->getUser();
 346          $output = $this->mContext->getOutput();
 347          $lang = $this->mContext->getLanguage();
 348          $cascadingRestrictionLevels = $this->mContext->getConfig()->get( 'CascadingRestrictionLevels' );
 349          $out = '';
 350          if ( !$this->disabled ) {
 351              $output->addModules( 'mediawiki.legacy.protect' );
 352              $output->addJsConfigVars( 'wgCascadeableLevels', $cascadingRestrictionLevels );
 353              $out .= Xml::openElement( 'form', array( 'method' => 'post',
 354                  'action' => $this->mTitle->getLocalURL( 'action=protect' ),
 355                  'id' => 'mw-Protect-Form' ) );
 356          }
 357  
 358          $out .= Xml::openElement( 'fieldset' ) .
 359              Xml::element( 'legend', null, wfMessage( 'protect-legend' )->text() ) .
 360              Xml::openElement( 'table', array( 'id' => 'mwProtectSet' ) ) .
 361              Xml::openElement( 'tbody' );
 362  
 363          $scExpiryOptions = wfMessage( 'protect-expiry-options' )->inContentLanguage()->text();
 364          $showProtectOptions = $scExpiryOptions !== '-' && !$this->disabled;
 365  
 366          // Not all languages have V_x <-> N_x relation
 367          foreach ( $this->mRestrictions as $action => $selected ) {
 368              // Messages:
 369              // restriction-edit, restriction-move, restriction-create, restriction-upload
 370              $msg = wfMessage( 'restriction-' . $action );
 371              $out .= "<tr><td>" .
 372              Xml::openElement( 'fieldset' ) .
 373              Xml::element( 'legend', null, $msg->exists() ? $msg->text() : $action ) .
 374              Xml::openElement( 'table', array( 'id' => "mw-protect-table-$action" ) ) .
 375                  "<tr><td>" . $this->buildSelector( $action, $selected ) . "</td></tr><tr><td>";
 376  
 377              $mProtectexpiry = Xml::label(
 378                  wfMessage( 'protectexpiry' )->text(),
 379                  "mwProtectExpirySelection-$action"
 380              );
 381              $mProtectother = Xml::label(
 382                  wfMessage( 'protect-othertime' )->text(),
 383                  "mwProtect-$action-expires"
 384              );
 385  
 386              $expiryFormOptions = '';
 387              if ( $this->mExistingExpiry[$action] ) {
 388                  if ( $this->mExistingExpiry[$action] == 'infinity' ) {
 389                      $existingExpiryMessage = wfMessage( 'protect-existing-expiry-infinity' );
 390                  } else {
 391                      $timestamp = $lang->timeanddate( $this->mExistingExpiry[$action], true );
 392                      $d = $lang->date( $this->mExistingExpiry[$action], true );
 393                      $t = $lang->time( $this->mExistingExpiry[$action], true );
 394                      $existingExpiryMessage = wfMessage( 'protect-existing-expiry', $timestamp, $d, $t );
 395                  }
 396                  $expiryFormOptions .=
 397                      Xml::option(
 398                          $existingExpiryMessage->text(),
 399                          'existing',
 400                          $this->mExpirySelection[$action] == 'existing'
 401                      ) . "\n";
 402              }
 403  
 404              $expiryFormOptions .= Xml::option(
 405                  wfMessage( 'protect-othertime-op' )->text(),
 406                  "othertime"
 407              ) . "\n";
 408              foreach ( explode( ',', $scExpiryOptions ) as $option ) {
 409                  if ( strpos( $option, ":" ) === false ) {
 410                      $show = $value = $option;
 411                  } else {
 412                      list( $show, $value ) = explode( ":", $option );
 413                  }
 414                  $show = htmlspecialchars( $show );
 415                  $value = htmlspecialchars( $value );
 416                  $expiryFormOptions .= Xml::option(
 417                      $show,
 418                      $value,
 419                      $this->mExpirySelection[$action] === $value
 420                  ) . "\n";
 421              }
 422              # Add expiry dropdown
 423              if ( $showProtectOptions && !$this->disabled ) {
 424                  $out .= "
 425                      <table><tr>
 426                          <td class='mw-label'>
 427                              {$mProtectexpiry}
 428                          </td>
 429                          <td class='mw-input'>" .
 430                              Xml::tags( 'select',
 431                                  array(
 432                                      'id' => "mwProtectExpirySelection-$action",
 433                                      'name' => "wpProtectExpirySelection-$action",
 434                                      'tabindex' => '2' ) + $this->disabledAttrib,
 435                                  $expiryFormOptions ) .
 436                          "</td>
 437                      </tr></table>";
 438              }
 439              # Add custom expiry field
 440              $attribs = array( 'id' => "mwProtect-$action-expires" ) + $this->disabledAttrib;
 441              $out .= "<table><tr>
 442                      <td class='mw-label'>" .
 443                          $mProtectother .
 444                      '</td>
 445                      <td class="mw-input">' .
 446                          Xml::input( "mwProtect-expiry-$action", 50, $this->mExpiry[$action], $attribs ) .
 447                      '</td>
 448                  </tr></table>';
 449              $out .= "</td></tr>" .
 450              Xml::closeElement( 'table' ) .
 451              Xml::closeElement( 'fieldset' ) .
 452              "</td></tr>";
 453          }
 454          # Give extensions a chance to add items to the form
 455          wfRunHooks( 'ProtectionForm::buildForm', array( $this->mArticle, &$out ) );
 456  
 457          $out .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
 458  
 459          // JavaScript will add another row with a value-chaining checkbox
 460          if ( $this->mTitle->exists() ) {
 461              $out .= Xml::openElement( 'table', array( 'id' => 'mw-protect-table2' ) ) .
 462                  Xml::openElement( 'tbody' );
 463              $out .= '<tr>
 464                      <td></td>
 465                      <td class="mw-input">' .
 466                          Xml::checkLabel(
 467                              wfMessage( 'protect-cascade' )->text(),
 468                              'mwProtect-cascade',
 469                              'mwProtect-cascade',
 470                              $this->mCascade, $this->disabledAttrib
 471                          ) .
 472                      "</td>
 473                  </tr>\n";
 474              $out .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
 475          }
 476  
 477          # Add manual and custom reason field/selects as well as submit
 478          if ( !$this->disabled ) {
 479              $mProtectreasonother = Xml::label(
 480                  wfMessage( 'protectcomment' )->text(),
 481                  'wpProtectReasonSelection'
 482              );
 483  
 484              $mProtectreason = Xml::label(
 485                  wfMessage( 'protect-otherreason' )->text(),
 486                  'mwProtect-reason'
 487              );
 488  
 489              $reasonDropDown = Xml::listDropDown( 'wpProtectReasonSelection',
 490                  wfMessage( 'protect-dropdown' )->inContentLanguage()->text(),
 491                  wfMessage( 'protect-otherreason-op' )->inContentLanguage()->text(),
 492                  $this->mReasonSelection,
 493                  'mwProtect-reason', 4 );
 494  
 495              $out .= Xml::openElement( 'table', array( 'id' => 'mw-protect-table3' ) ) .
 496                  Xml::openElement( 'tbody' );
 497              $out .= "
 498                  <tr>
 499                      <td class='mw-label'>
 500                          {$mProtectreasonother}
 501                      </td>
 502                      <td class='mw-input'>
 503                          {$reasonDropDown}
 504                      </td>
 505                  </tr>
 506                  <tr>
 507                      <td class='mw-label'>
 508                          {$mProtectreason}
 509                      </td>
 510                      <td class='mw-input'>" .
 511                          Xml::input( 'mwProtect-reason', 60, $this->mReason, array( 'type' => 'text',
 512                              'id' => 'mwProtect-reason', 'maxlength' => 180 ) ) .
 513                              // Limited maxlength as the database trims at 255 bytes and other texts
 514                              // chosen by dropdown menus on this page are also included in this database field.
 515                              // The byte limit of 180 bytes is enforced in javascript
 516                      "</td>
 517                  </tr>";
 518              # Disallow watching is user is not logged in
 519              if ( $user->isLoggedIn() ) {
 520                  $out .= "
 521                  <tr>
 522                      <td></td>
 523                      <td class='mw-input'>" .
 524                          Xml::checkLabel( wfMessage( 'watchthis' )->text(),
 525                              'mwProtectWatch', 'mwProtectWatch',
 526                              $user->isWatched( $this->mTitle ) || $user->getOption( 'watchdefault' ) ) .
 527                      "</td>
 528                  </tr>";
 529              }
 530              $out .= "
 531                  <tr>
 532                      <td></td>
 533                      <td class='mw-submit'>" .
 534                          Xml::submitButton(
 535                              wfMessage( 'confirm' )->text(),
 536                              array( 'id' => 'mw-Protect-submit' )
 537                          ) .
 538                      "</td>
 539                  </tr>\n";
 540              $out .= Xml::closeElement( 'tbody' ) . Xml::closeElement( 'table' );
 541          }
 542          $out .= Xml::closeElement( 'fieldset' );
 543  
 544          if ( $user->isAllowed( 'editinterface' ) ) {
 545              $title = Title::makeTitle( NS_MEDIAWIKI, 'Protect-dropdown' );
 546              $link = Linker::link(
 547                  $title,
 548                  wfMessage( 'protect-edit-reasonlist' )->escaped(),
 549                  array(),
 550                  array( 'action' => 'edit' )
 551              );
 552              $out .= '<p class="mw-protect-editreasons">' . $link . '</p>';
 553          }
 554  
 555          if ( !$this->disabled ) {
 556              $out .= Html::hidden(
 557                  'wpEditToken',
 558                  $user->getEditToken( array( 'protect', $this->mTitle->getPrefixedDBkey() ) )
 559              );
 560              $out .= Xml::closeElement( 'form' );
 561          }
 562  
 563          return $out;
 564      }
 565  
 566      /**
 567       * Build protection level selector
 568       *
 569       * @param string $action Action to protect
 570       * @param string $selected Current protection level
 571       * @return string HTML fragment
 572       */
 573  	function buildSelector( $action, $selected ) {
 574          // If the form is disabled, display all relevant levels. Otherwise,
 575          // just show the ones this user can use.
 576          $levels = MWNamespace::getRestrictionLevels( $this->mTitle->getNamespace(),
 577              $this->disabled ? null : $this->mContext->getUser()
 578          );
 579  
 580          $id = 'mwProtect-level-' . $action;
 581          $attribs = array(
 582              'id' => $id,
 583              'name' => $id,
 584              'size' => count( $levels ),
 585          ) + $this->disabledAttrib;
 586  
 587          $out = Xml::openElement( 'select', $attribs );
 588          foreach ( $levels as $key ) {
 589              $out .= Xml::option( $this->getOptionLabel( $key ), $key, $key == $selected );
 590          }
 591          $out .= Xml::closeElement( 'select' );
 592          return $out;
 593      }
 594  
 595      /**
 596       * Prepare the label for a protection selector option
 597       *
 598       * @param string $permission Permission required
 599       * @return string
 600       */
 601  	private function getOptionLabel( $permission ) {
 602          if ( $permission == '' ) {
 603              return wfMessage( 'protect-default' )->text();
 604          } else {
 605              // Messages: protect-level-autoconfirmed, protect-level-sysop
 606              $msg = wfMessage( "protect-level-{$permission}" );
 607              if ( $msg->exists() ) {
 608                  return $msg->text();
 609              }
 610              return wfMessage( 'protect-fallback', $permission )->text();
 611          }
 612      }
 613  
 614      /**
 615       * Show protection long extracts for this page
 616       *
 617       * @param OutputPage $out
 618       * @access private
 619       */
 620  	function showLogExtract( &$out ) {
 621          # Show relevant lines from the protection log:
 622          $protectLogPage = new LogPage( 'protect' );
 623          $out->addHTML( Xml::element( 'h2', null, $protectLogPage->getName()->text() ) );
 624          LogEventsList::showLogExtract( $out, 'protect', $this->mTitle );
 625          # Let extensions add other relevant log extracts
 626          wfRunHooks( 'ProtectionForm::showLogExtract', array( $this->mArticle, $out ) );
 627      }
 628  }


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