[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

/includes/installer/ -> WebInstallerPage.php (source)

   1  <?php
   2  /**
   3   * Base code for web installer pages.
   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 Deployment
  22   */
  23  
  24  /**
  25   * Abstract class to define pages for the web installer.
  26   *
  27   * @ingroup Deployment
  28   * @since 1.17
  29   */
  30  abstract class WebInstallerPage {
  31  
  32      /**
  33       * The WebInstaller object this WebInstallerPage belongs to.
  34       *
  35       * @var WebInstaller
  36       */
  37      public $parent;
  38  
  39      /**
  40       * @return string
  41       */
  42      abstract public function execute();
  43  
  44      /**
  45       * @param WebInstaller $parent
  46       */
  47  	public function __construct( WebInstaller $parent ) {
  48          $this->parent = $parent;
  49      }
  50  
  51      /**
  52       * Is this a slow-running page in the installer? If so, WebInstaller will
  53       * set_time_limit(0) before calling execute(). Right now this only applies
  54       * to Install and Upgrade pages
  55       *
  56       * @return bool Always false in this default implementation.
  57       */
  58  	public function isSlow() {
  59          return false;
  60      }
  61  
  62      /**
  63       * @param string $html
  64       */
  65  	public function addHTML( $html ) {
  66          $this->parent->output->addHTML( $html );
  67      }
  68  
  69  	public function startForm() {
  70          $this->addHTML(
  71              "<div class=\"config-section\">\n" .
  72              Html::openElement(
  73                  'form',
  74                  array(
  75                      'method' => 'post',
  76                      'action' => $this->parent->getUrl( array( 'page' => $this->getName() ) )
  77                  )
  78              ) . "\n"
  79          );
  80      }
  81  
  82      /**
  83       * @param string|bool $continue
  84       * @param string|bool $back
  85       */
  86  	public function endForm( $continue = 'continue', $back = 'back' ) {
  87          $s = "<div class=\"config-submit\">\n";
  88          $id = $this->getId();
  89  
  90          if ( $id === false ) {
  91              $s .= Html::hidden( 'lastPage', $this->parent->request->getVal( 'lastPage' ) );
  92          }
  93  
  94          if ( $continue ) {
  95              // Fake submit button for enter keypress (bug 26267)
  96              // Messages: config-continue, config-restart, config-regenerate
  97              $s .= Xml::submitButton(
  98                  wfMessage( "config-$continue" )->text(),
  99                  array(
 100                      'name' => "enter-$continue",
 101                      'style' => 'visibility:hidden;overflow:hidden;width:1px;margin:0'
 102                  )
 103              ) . "\n";
 104          }
 105  
 106          if ( $back ) {
 107              // Message: config-back
 108              $s .= Xml::submitButton(
 109                  wfMessage( "config-$back" )->text(),
 110                  array(
 111                      'name' => "submit-$back",
 112                      'tabindex' => $this->parent->nextTabIndex()
 113                  )
 114              ) . "\n";
 115          }
 116  
 117          if ( $continue ) {
 118              // Messages: config-continue, config-restart, config-regenerate
 119              $s .= Xml::submitButton(
 120                  wfMessage( "config-$continue" )->text(),
 121                  array(
 122                      'name' => "submit-$continue",
 123                      'tabindex' => $this->parent->nextTabIndex(),
 124                  )
 125              ) . "\n";
 126          }
 127  
 128          $s .= "</div></form></div>\n";
 129          $this->addHTML( $s );
 130      }
 131  
 132      /**
 133       * @return string
 134       */
 135  	public function getName() {
 136          return str_replace( 'WebInstaller', '', get_class( $this ) );
 137      }
 138  
 139      /**
 140       * @return string
 141       */
 142  	protected function getId() {
 143          return array_search( $this->getName(), $this->parent->pageSequence );
 144      }
 145  
 146      /**
 147       * @param string $var
 148       * @param mixed $default
 149       *
 150       * @return mixed
 151       */
 152  	public function getVar( $var, $default = null ) {
 153          return $this->parent->getVar( $var, $default );
 154      }
 155  
 156      /**
 157       * @param string $name
 158       * @param mixed $value
 159       */
 160  	public function setVar( $name, $value ) {
 161          $this->parent->setVar( $name, $value );
 162      }
 163  
 164      /**
 165       * Get the starting tags of a fieldset.
 166       *
 167       * @param string $legend Message name
 168       *
 169       * @return string
 170       */
 171  	protected function getFieldsetStart( $legend ) {
 172          return "\n<fieldset><legend>" . wfMessage( $legend )->escaped() . "</legend>\n";
 173      }
 174  
 175      /**
 176       * Get the end tag of a fieldset.
 177       *
 178       * @return string
 179       */
 180  	protected function getFieldsetEnd() {
 181          return "</fieldset>\n";
 182      }
 183  
 184      /**
 185       * Opens a textarea used to display the progress of a long operation
 186       */
 187  	protected function startLiveBox() {
 188          $this->addHTML(
 189              '<div id="config-spinner" style="display:none;">' .
 190              '<img src="images/ajax-loader.gif" /></div>' .
 191              '<script>jQuery( "#config-spinner" ).show();</script>' .
 192              '<div id="config-live-log">' .
 193              '<textarea name="LiveLog" rows="10" cols="30" readonly="readonly">'
 194          );
 195          $this->parent->output->flush();
 196      }
 197  
 198      /**
 199       * Opposite to WebInstallerPage::startLiveBox
 200       */
 201  	protected function endLiveBox() {
 202          $this->addHTML( '</textarea></div>
 203  <script>jQuery( "#config-spinner" ).hide()</script>' );
 204          $this->parent->output->flush();
 205      }
 206  
 207  }
 208  
 209  class WebInstallerLanguage extends WebInstallerPage {
 210  
 211      /**
 212       * @return string|null
 213       */
 214  	public function execute() {
 215          global $wgLang;
 216          $r = $this->parent->request;
 217          $userLang = $r->getVal( 'uselang' );
 218          $contLang = $r->getVal( 'ContLang' );
 219  
 220          $languages = Language::fetchLanguageNames();
 221          $lifetime = intval( ini_get( 'session.gc_maxlifetime' ) );
 222          if ( !$lifetime ) {
 223              $lifetime = 1440; // PHP default
 224          }
 225  
 226          if ( $r->wasPosted() ) {
 227              # Do session test
 228              if ( $this->parent->getSession( 'test' ) === null ) {
 229                  $requestTime = $r->getVal( 'LanguageRequestTime' );
 230                  if ( !$requestTime ) {
 231                      // The most likely explanation is that the user was knocked back
 232                      // from another page on POST due to session expiry
 233                      $msg = 'config-session-expired';
 234                  } elseif ( time() - $requestTime > $lifetime ) {
 235                      $msg = 'config-session-expired';
 236                  } else {
 237                      $msg = 'config-no-session';
 238                  }
 239                  $this->parent->showError( $msg, $wgLang->formatTimePeriod( $lifetime ) );
 240              } else {
 241                  if ( isset( $languages[$userLang] ) ) {
 242                      $this->setVar( '_UserLang', $userLang );
 243                  }
 244                  if ( isset( $languages[$contLang] ) ) {
 245                      $this->setVar( 'wgLanguageCode', $contLang );
 246                  }
 247  
 248                  return 'continue';
 249              }
 250          } elseif ( $this->parent->showSessionWarning ) {
 251              # The user was knocked back from another page to the start
 252              # This probably indicates a session expiry
 253              $this->parent->showError( 'config-session-expired',
 254                  $wgLang->formatTimePeriod( $lifetime ) );
 255          }
 256  
 257          $this->parent->setSession( 'test', true );
 258  
 259          if ( !isset( $languages[$userLang] ) ) {
 260              $userLang = $this->getVar( '_UserLang', 'en' );
 261          }
 262          if ( !isset( $languages[$contLang] ) ) {
 263              $contLang = $this->getVar( 'wgLanguageCode', 'en' );
 264          }
 265          $this->startForm();
 266          $s = Html::hidden( 'LanguageRequestTime', time() ) .
 267              $this->getLanguageSelector( 'uselang', 'config-your-language', $userLang,
 268                  $this->parent->getHelpBox( 'config-your-language-help' ) ) .
 269              $this->getLanguageSelector( 'ContLang', 'config-wiki-language', $contLang,
 270                  $this->parent->getHelpBox( 'config-wiki-language-help' ) );
 271          $this->addHTML( $s );
 272          $this->endForm( 'continue', false );
 273  
 274          return null;
 275      }
 276  
 277      /**
 278       * Get a "<select>" for selecting languages.
 279       *
 280       * @param string $name
 281       * @param string $label
 282       * @param string $selectedCode
 283       * @param string $helpHtml
 284       *
 285       * @return string
 286       */
 287  	public function getLanguageSelector( $name, $label, $selectedCode, $helpHtml = '' ) {
 288          global $wgDummyLanguageCodes;
 289  
 290          $s = $helpHtml;
 291  
 292          $s .= Html::openElement( 'select', array( 'id' => $name, 'name' => $name,
 293                  'tabindex' => $this->parent->nextTabIndex() ) ) . "\n";
 294  
 295          $languages = Language::fetchLanguageNames();
 296          ksort( $languages );
 297          foreach ( $languages as $code => $lang ) {
 298              if ( isset( $wgDummyLanguageCodes[$code] ) ) {
 299                  continue;
 300              }
 301              $s .= "\n" . Xml::option( "$code - $lang", $code, $code == $selectedCode );
 302          }
 303          $s .= "\n</select>\n";
 304  
 305          return $this->parent->label( $label, $name, $s );
 306      }
 307  
 308  }
 309  
 310  class WebInstallerExistingWiki extends WebInstallerPage {
 311  
 312      /**
 313       * @return string
 314       */
 315  	public function execute() {
 316          // If there is no LocalSettings.php, continue to the installer welcome page
 317          $vars = Installer::getExistingLocalSettings();
 318          if ( !$vars ) {
 319              return 'skip';
 320          }
 321  
 322          // Check if the upgrade key supplied to the user has appeared in LocalSettings.php
 323          if ( $vars['wgUpgradeKey'] !== false
 324              && $this->getVar( '_UpgradeKeySupplied' )
 325              && $this->getVar( 'wgUpgradeKey' ) === $vars['wgUpgradeKey']
 326          ) {
 327              // It's there, so the user is authorized
 328              $status = $this->handleExistingUpgrade( $vars );
 329              if ( $status->isOK() ) {
 330                  return 'skip';
 331              } else {
 332                  $this->startForm();
 333                  $this->parent->showStatusBox( $status );
 334                  $this->endForm( 'continue' );
 335  
 336                  return 'output';
 337              }
 338          }
 339  
 340          // If there is no $wgUpgradeKey, tell the user to add one to LocalSettings.php
 341          if ( $vars['wgUpgradeKey'] === false ) {
 342              if ( $this->getVar( 'wgUpgradeKey', false ) === false ) {
 343                  $secretKey = $this->getVar( 'wgSecretKey' ); // preserve $wgSecretKey
 344                  $this->parent->generateKeys();
 345                  $this->setVar( 'wgSecretKey', $secretKey );
 346                  $this->setVar( '_UpgradeKeySupplied', true );
 347              }
 348              $this->startForm();
 349              $this->addHTML( $this->parent->getInfoBox(
 350                  wfMessage( 'config-upgrade-key-missing', "<pre dir=\"ltr\">\$wgUpgradeKey = '" .
 351                      $this->getVar( 'wgUpgradeKey' ) . "';</pre>" )->plain()
 352              ) );
 353              $this->endForm( 'continue' );
 354  
 355              return 'output';
 356          }
 357  
 358          // If there is an upgrade key, but it wasn't supplied, prompt the user to enter it
 359  
 360          $r = $this->parent->request;
 361          if ( $r->wasPosted() ) {
 362              $key = $r->getText( 'config_wgUpgradeKey' );
 363              if ( !$key || $key !== $vars['wgUpgradeKey'] ) {
 364                  $this->parent->showError( 'config-localsettings-badkey' );
 365                  $this->showKeyForm();
 366  
 367                  return 'output';
 368              }
 369              // Key was OK
 370              $status = $this->handleExistingUpgrade( $vars );
 371              if ( $status->isOK() ) {
 372                  return 'continue';
 373              } else {
 374                  $this->parent->showStatusBox( $status );
 375                  $this->showKeyForm();
 376  
 377                  return 'output';
 378              }
 379          } else {
 380              $this->showKeyForm();
 381  
 382              return 'output';
 383          }
 384      }
 385  
 386      /**
 387       * Show the "enter key" form
 388       */
 389  	protected function showKeyForm() {
 390          $this->startForm();
 391          $this->addHTML(
 392              $this->parent->getInfoBox( wfMessage( 'config-localsettings-upgrade' )->plain() ) .
 393              '<br />' .
 394              $this->parent->getTextBox( array(
 395                  'var' => 'wgUpgradeKey',
 396                  'label' => 'config-localsettings-key',
 397                  'attribs' => array( 'autocomplete' => 'off' ),
 398              ) )
 399          );
 400          $this->endForm( 'continue' );
 401      }
 402  
 403      /**
 404       * @param string[] $names
 405       * @param mixed[] $vars
 406       *
 407       * @return Status
 408       */
 409  	protected function importVariables( $names, $vars ) {
 410          $status = Status::newGood();
 411          foreach ( $names as $name ) {
 412              if ( !isset( $vars[$name] ) ) {
 413                  $status->fatal( 'config-localsettings-incomplete', $name );
 414              }
 415              $this->setVar( $name, $vars[$name] );
 416          }
 417  
 418          return $status;
 419      }
 420  
 421      /**
 422       * Initiate an upgrade of the existing database
 423       *
 424       * @param mixed[] $vars Variables from LocalSettings.php
 425       *
 426       * @return Status
 427       */
 428  	protected function handleExistingUpgrade( $vars ) {
 429          // Check $wgDBtype
 430          if ( !isset( $vars['wgDBtype'] ) ||
 431              !in_array( $vars['wgDBtype'], Installer::getDBTypes() )
 432          ) {
 433              return Status::newFatal( 'config-localsettings-connection-error', '' );
 434          }
 435  
 436          // Set the relevant variables from LocalSettings.php
 437          $requiredVars = array( 'wgDBtype' );
 438          $status = $this->importVariables( $requiredVars, $vars );
 439          $installer = $this->parent->getDBInstaller();
 440          $status->merge( $this->importVariables( $installer->getGlobalNames(), $vars ) );
 441          if ( !$status->isOK() ) {
 442              return $status;
 443          }
 444  
 445          if ( isset( $vars['wgDBadminuser'] ) ) {
 446              $this->setVar( '_InstallUser', $vars['wgDBadminuser'] );
 447          } else {
 448              $this->setVar( '_InstallUser', $vars['wgDBuser'] );
 449          }
 450          if ( isset( $vars['wgDBadminpassword'] ) ) {
 451              $this->setVar( '_InstallPassword', $vars['wgDBadminpassword'] );
 452          } else {
 453              $this->setVar( '_InstallPassword', $vars['wgDBpassword'] );
 454          }
 455  
 456          // Test the database connection
 457          $status = $installer->getConnection();
 458          if ( !$status->isOK() ) {
 459              // Adjust the error message to explain things correctly
 460              $status->replaceMessage( 'config-connection-error',
 461                  'config-localsettings-connection-error' );
 462  
 463              return $status;
 464          }
 465  
 466          // All good
 467          $this->setVar( '_ExistingDBSettings', true );
 468  
 469          return $status;
 470      }
 471  
 472  }
 473  
 474  class WebInstallerWelcome extends WebInstallerPage {
 475  
 476      /**
 477       * @return string
 478       */
 479  	public function execute() {
 480          if ( $this->parent->request->wasPosted() ) {
 481              if ( $this->getVar( '_Environment' ) ) {
 482                  return 'continue';
 483              }
 484          }
 485          $this->parent->output->addWikiText( wfMessage( 'config-welcome' )->plain() );
 486          $status = $this->parent->doEnvironmentChecks();
 487          if ( $status->isGood() ) {
 488              $this->parent->output->addHTML( '<span class="success-message">' .
 489                  wfMessage( 'config-env-good' )->escaped() . '</span>' );
 490              $this->parent->output->addWikiText( wfMessage( 'config-copyright',
 491                  SpecialVersion::getCopyrightAndAuthorList() )->plain() );
 492              $this->startForm();
 493              $this->endForm();
 494          } else {
 495              $this->parent->showStatusMessage( $status );
 496          }
 497  
 498          return '';
 499      }
 500  
 501  }
 502  
 503  class WebInstallerDBConnect extends WebInstallerPage {
 504  
 505      /**
 506       * @return string|null When string, "skip" or "continue"
 507       */
 508  	public function execute() {
 509          if ( $this->getVar( '_ExistingDBSettings' ) ) {
 510              return 'skip';
 511          }
 512  
 513          $r = $this->parent->request;
 514          if ( $r->wasPosted() ) {
 515              $status = $this->submit();
 516  
 517              if ( $status->isGood() ) {
 518                  $this->setVar( '_UpgradeDone', false );
 519  
 520                  return 'continue';
 521              } else {
 522                  $this->parent->showStatusBox( $status );
 523              }
 524          }
 525  
 526          $this->startForm();
 527  
 528          $types = "<ul class=\"config-settings-block\">\n";
 529          $settings = '';
 530          $defaultType = $this->getVar( 'wgDBtype' );
 531  
 532          // Messages: config-dbsupport-mysql, config-dbsupport-postgres, config-dbsupport-oracle,
 533          // config-dbsupport-sqlite, config-dbsupport-mssql
 534          $dbSupport = '';
 535          foreach ( Installer::getDBTypes() as $type ) {
 536              $dbSupport .= wfMessage( "config-dbsupport-$type" )->plain() . "\n";
 537          }
 538          $this->addHTML( $this->parent->getInfoBox(
 539              wfMessage( 'config-support-info', trim( $dbSupport ) )->text() ) );
 540  
 541          // It's possible that the library for the default DB type is not compiled in.
 542          // In that case, instead select the first supported DB type in the list.
 543          $compiledDBs = $this->parent->getCompiledDBs();
 544          if ( !in_array( $defaultType, $compiledDBs ) ) {
 545              $defaultType = $compiledDBs[0];
 546          }
 547  
 548          foreach ( $compiledDBs as $type ) {
 549              $installer = $this->parent->getDBInstaller( $type );
 550              $types .=
 551                  '<li>' .
 552                  Xml::radioLabel(
 553                      $installer->getReadableName(),
 554                      'DBType',
 555                      $type,
 556                      "DBType_$type",
 557                      $type == $defaultType,
 558                      array( 'class' => 'dbRadio', 'rel' => "DB_wrapper_$type" )
 559                  ) .
 560                  "</li>\n";
 561  
 562              // Messages: config-header-mysql, config-header-postgres, config-header-oracle,
 563              // config-header-sqlite
 564              $settings .= Html::openElement(
 565                      'div',
 566                      array(
 567                          'id' => 'DB_wrapper_' . $type,
 568                          'class' => 'dbWrapper'
 569                      )
 570                  ) .
 571                  Html::element( 'h3', array(), wfMessage( 'config-header-' . $type )->text() ) .
 572                  $installer->getConnectForm() .
 573                  "</div>\n";
 574          }
 575  
 576          $types .= "</ul><br style=\"clear: left\"/>\n";
 577  
 578          $this->addHTML( $this->parent->label( 'config-db-type', false, $types ) . $settings );
 579          $this->endForm();
 580  
 581          return null;
 582      }
 583  
 584      /**
 585       * @return Status
 586       */
 587  	public function submit() {
 588          $r = $this->parent->request;
 589          $type = $r->getVal( 'DBType' );
 590          if ( !$type ) {
 591              return Status::newFatal( 'config-invalid-db-type' );
 592          }
 593          $this->setVar( 'wgDBtype', $type );
 594          $installer = $this->parent->getDBInstaller( $type );
 595          if ( !$installer ) {
 596              return Status::newFatal( 'config-invalid-db-type' );
 597          }
 598  
 599          return $installer->submitConnectForm();
 600      }
 601  
 602  }
 603  
 604  class WebInstallerUpgrade extends WebInstallerPage {
 605  
 606      /**
 607       * @return bool Always true.
 608       */
 609  	public function isSlow() {
 610          return true;
 611      }
 612  
 613      /**
 614       * @return string|null
 615       */
 616  	public function execute() {
 617          if ( $this->getVar( '_UpgradeDone' ) ) {
 618              // Allow regeneration of LocalSettings.php, unless we are working
 619              // from a pre-existing LocalSettings.php file and we want to avoid
 620              // leaking its contents
 621              if ( $this->parent->request->wasPosted() && !$this->getVar( '_ExistingDBSettings' ) ) {
 622                  // Done message acknowledged
 623                  return 'continue';
 624              } else {
 625                  // Back button click
 626                  // Show the done message again
 627                  // Make them click back again if they want to do the upgrade again
 628                  $this->showDoneMessage();
 629  
 630                  return 'output';
 631              }
 632          }
 633  
 634          // wgDBtype is generally valid here because otherwise the previous page
 635          // (connect) wouldn't have declared its happiness
 636          $type = $this->getVar( 'wgDBtype' );
 637          $installer = $this->parent->getDBInstaller( $type );
 638  
 639          if ( !$installer->needsUpgrade() ) {
 640              return 'skip';
 641          }
 642  
 643          if ( $this->parent->request->wasPosted() ) {
 644              $installer->preUpgrade();
 645  
 646              $this->startLiveBox();
 647              $result = $installer->doUpgrade();
 648              $this->endLiveBox();
 649  
 650              if ( $result ) {
 651                  // If they're going to possibly regenerate LocalSettings, we
 652                  // need to create the upgrade/secret keys. Bug 26481
 653                  if ( !$this->getVar( '_ExistingDBSettings' ) ) {
 654                      $this->parent->generateKeys();
 655                  }
 656                  $this->setVar( '_UpgradeDone', true );
 657                  $this->showDoneMessage();
 658  
 659                  return 'output';
 660              }
 661          }
 662  
 663          $this->startForm();
 664          $this->addHTML( $this->parent->getInfoBox(
 665              wfMessage( 'config-can-upgrade', $GLOBALS['wgVersion'] )->plain() ) );
 666          $this->endForm();
 667  
 668          return null;
 669      }
 670  
 671  	public function showDoneMessage() {
 672          $this->startForm();
 673          $regenerate = !$this->getVar( '_ExistingDBSettings' );
 674          if ( $regenerate ) {
 675              $msg = 'config-upgrade-done';
 676          } else {
 677              $msg = 'config-upgrade-done-no-regenerate';
 678          }
 679          $this->parent->disableLinkPopups();
 680          $this->addHTML(
 681              $this->parent->getInfoBox(
 682                  wfMessage( $msg,
 683                      $this->getVar( 'wgServer' ) .
 684                      $this->getVar( 'wgScriptPath' ) . '/index' .
 685                      $this->getVar( 'wgScriptExtension' )
 686                  )->plain(), 'tick-32.png'
 687              )
 688          );
 689          $this->parent->restoreLinkPopups();
 690          $this->endForm( $regenerate ? 'regenerate' : false, false );
 691      }
 692  
 693  }
 694  
 695  class WebInstallerDBSettings extends WebInstallerPage {
 696  
 697      /**
 698       * @return string|null
 699       */
 700  	public function execute() {
 701          $installer = $this->parent->getDBInstaller( $this->getVar( 'wgDBtype' ) );
 702  
 703          $r = $this->parent->request;
 704          if ( $r->wasPosted() ) {
 705              $status = $installer->submitSettingsForm();
 706              if ( $status === false ) {
 707                  return 'skip';
 708              } elseif ( $status->isGood() ) {
 709                  return 'continue';
 710              } else {
 711                  $this->parent->showStatusBox( $status );
 712              }
 713          }
 714  
 715          $form = $installer->getSettingsForm();
 716          if ( $form === false ) {
 717              return 'skip';
 718          }
 719  
 720          $this->startForm();
 721          $this->addHTML( $form );
 722          $this->endForm();
 723  
 724          return null;
 725      }
 726  
 727  }
 728  
 729  class WebInstallerName extends WebInstallerPage {
 730  
 731      /**
 732       * @return string
 733       */
 734  	public function execute() {
 735          $r = $this->parent->request;
 736          if ( $r->wasPosted() ) {
 737              if ( $this->submit() ) {
 738                  return 'continue';
 739              }
 740          }
 741  
 742          $this->startForm();
 743  
 744          // Encourage people to not name their site 'MediaWiki' by blanking the
 745          // field. I think that was the intent with the original $GLOBALS['wgSitename']
 746          // but these two always were the same so had the effect of making the
 747          // installer forget $wgSitename when navigating back to this page.
 748          if ( $this->getVar( 'wgSitename' ) == 'MediaWiki' ) {
 749              $this->setVar( 'wgSitename', '' );
 750          }
 751  
 752          // Set wgMetaNamespace to something valid before we show the form.
 753          // $wgMetaNamespace defaults to $wgSiteName which is 'MediaWiki'
 754          $metaNS = $this->getVar( 'wgMetaNamespace' );
 755          $this->setVar(
 756              'wgMetaNamespace',
 757              wfMessage( 'config-ns-other-default' )->inContentLanguage()->text()
 758          );
 759  
 760          $this->addHTML(
 761              $this->parent->getTextBox( array(
 762                  'var' => 'wgSitename',
 763                  'label' => 'config-site-name',
 764                  'help' => $this->parent->getHelpBox( 'config-site-name-help' )
 765              ) ) .
 766              // getRadioSet() builds a set of labeled radio buttons.
 767              // For grep: The following messages are used as the item labels:
 768              // config-ns-site-name, config-ns-generic, config-ns-other
 769              $this->parent->getRadioSet( array(
 770                  'var' => '_NamespaceType',
 771                  'label' => 'config-project-namespace',
 772                  'itemLabelPrefix' => 'config-ns-',
 773                  'values' => array( 'site-name', 'generic', 'other' ),
 774                  'commonAttribs' => array( 'class' => 'enableForOther',
 775                      'rel' => 'config_wgMetaNamespace' ),
 776                  'help' => $this->parent->getHelpBox( 'config-project-namespace-help' )
 777              ) ) .
 778              $this->parent->getTextBox( array(
 779                  'var' => 'wgMetaNamespace',
 780                  'label' => '', // @todo Needs a label?
 781                  'attribs' => array( 'readonly' => 'readonly', 'class' => 'enabledByOther' )
 782              ) ) .
 783              $this->getFieldSetStart( 'config-admin-box' ) .
 784              $this->parent->getTextBox( array(
 785                  'var' => '_AdminName',
 786                  'label' => 'config-admin-name',
 787                  'help' => $this->parent->getHelpBox( 'config-admin-help' )
 788              ) ) .
 789              $this->parent->getPasswordBox( array(
 790                  'var' => '_AdminPassword',
 791                  'label' => 'config-admin-password',
 792              ) ) .
 793              $this->parent->getPasswordBox( array(
 794                  'var' => '_AdminPasswordConfirm',
 795                  'label' => 'config-admin-password-confirm'
 796              ) ) .
 797              $this->parent->getTextBox( array(
 798                  'var' => '_AdminEmail',
 799                  'label' => 'config-admin-email',
 800                  'help' => $this->parent->getHelpBox( 'config-admin-email-help' )
 801              ) ) .
 802              $this->parent->getCheckBox( array(
 803                  'var' => '_Subscribe',
 804                  'label' => 'config-subscribe',
 805                  'help' => $this->parent->getHelpBox( 'config-subscribe-help' )
 806              ) ) .
 807              $this->getFieldSetEnd() .
 808              $this->parent->getInfoBox( wfMessage( 'config-almost-done' )->text() ) .
 809              // getRadioSet() builds a set of labeled radio buttons.
 810              // For grep: The following messages are used as the item labels:
 811              // config-optional-continue, config-optional-skip
 812              $this->parent->getRadioSet( array(
 813                  'var' => '_SkipOptional',
 814                  'itemLabelPrefix' => 'config-optional-',
 815                  'values' => array( 'continue', 'skip' )
 816              ) )
 817          );
 818  
 819          // Restore the default value
 820          $this->setVar( 'wgMetaNamespace', $metaNS );
 821  
 822          $this->endForm();
 823  
 824          return 'output';
 825      }
 826  
 827      /**
 828       * @return bool
 829       */
 830  	public function submit() {
 831          $retVal = true;
 832          $this->parent->setVarsFromRequest( array( 'wgSitename', '_NamespaceType',
 833              '_AdminName', '_AdminPassword', '_AdminPasswordConfirm', '_AdminEmail',
 834              '_Subscribe', '_SkipOptional', 'wgMetaNamespace' ) );
 835  
 836          // Validate site name
 837          if ( strval( $this->getVar( 'wgSitename' ) ) === '' ) {
 838              $this->parent->showError( 'config-site-name-blank' );
 839              $retVal = false;
 840          }
 841  
 842          // Fetch namespace
 843          $nsType = $this->getVar( '_NamespaceType' );
 844          if ( $nsType == 'site-name' ) {
 845              $name = $this->getVar( 'wgSitename' );
 846              // Sanitize for namespace
 847              // This algorithm should match the JS one in WebInstallerOutput.php
 848              $name = preg_replace( '/[\[\]\{\}|#<>%+? ]/', '_', $name );
 849              $name = str_replace( '&', '&amp;', $name );
 850              $name = preg_replace( '/__+/', '_', $name );
 851              $name = ucfirst( trim( $name, '_' ) );
 852          } elseif ( $nsType == 'generic' ) {
 853              $name = wfMessage( 'config-ns-generic' )->text();
 854          } else { // other
 855              $name = $this->getVar( 'wgMetaNamespace' );
 856          }
 857  
 858          // Validate namespace
 859          if ( strpos( $name, ':' ) !== false ) {
 860              $good = false;
 861          } else {
 862              // Title-style validation
 863              $title = Title::newFromText( $name );
 864              if ( !$title ) {
 865                  $good = $nsType == 'site-name';
 866              } else {
 867                  $name = $title->getDBkey();
 868                  $good = true;
 869              }
 870          }
 871          if ( !$good ) {
 872              $this->parent->showError( 'config-ns-invalid', $name );
 873              $retVal = false;
 874          }
 875  
 876          // Make sure it won't conflict with any existing namespaces
 877          global $wgContLang;
 878          $nsIndex = $wgContLang->getNsIndex( $name );
 879          if ( $nsIndex !== false && $nsIndex !== NS_PROJECT ) {
 880              $this->parent->showError( 'config-ns-conflict', $name );
 881              $retVal = false;
 882          }
 883  
 884          $this->setVar( 'wgMetaNamespace', $name );
 885  
 886          // Validate username for creation
 887          $name = $this->getVar( '_AdminName' );
 888          if ( strval( $name ) === '' ) {
 889              $this->parent->showError( 'config-admin-name-blank' );
 890              $cname = $name;
 891              $retVal = false;
 892          } else {
 893              $cname = User::getCanonicalName( $name, 'creatable' );
 894              if ( $cname === false ) {
 895                  $this->parent->showError( 'config-admin-name-invalid', $name );
 896                  $retVal = false;
 897              } else {
 898                  $this->setVar( '_AdminName', $cname );
 899              }
 900          }
 901  
 902          // Validate password
 903          $msg = false;
 904          $pwd = $this->getVar( '_AdminPassword' );
 905          $user = User::newFromName( $cname );
 906          if ( $user ) {
 907              $valid = $user->getPasswordValidity( $pwd );
 908          } else {
 909              $valid = 'config-admin-name-invalid';
 910          }
 911          if ( strval( $pwd ) === '' ) {
 912              # $user->getPasswordValidity just checks for $wgMinimalPasswordLength.
 913              # This message is more specific and helpful.
 914              $msg = 'config-admin-password-blank';
 915          } elseif ( $pwd !== $this->getVar( '_AdminPasswordConfirm' ) ) {
 916              $msg = 'config-admin-password-mismatch';
 917          } elseif ( $valid !== true ) {
 918              $msg = $valid;
 919          }
 920          if ( $msg !== false ) {
 921              call_user_func_array( array( $this->parent, 'showError' ), (array)$msg );
 922              $this->setVar( '_AdminPassword', '' );
 923              $this->setVar( '_AdminPasswordConfirm', '' );
 924              $retVal = false;
 925          }
 926  
 927          // Validate e-mail if provided
 928          $email = $this->getVar( '_AdminEmail' );
 929          if ( $email && !Sanitizer::validateEmail( $email ) ) {
 930              $this->parent->showError( 'config-admin-error-bademail' );
 931              $retVal = false;
 932          }
 933          // If they asked to subscribe to mediawiki-announce but didn't give
 934          // an e-mail, show an error. Bug 29332
 935          if ( !$email && $this->getVar( '_Subscribe' ) ) {
 936              $this->parent->showError( 'config-subscribe-noemail' );
 937              $retVal = false;
 938          }
 939  
 940          return $retVal;
 941      }
 942  
 943  }
 944  
 945  class WebInstallerOptions extends WebInstallerPage {
 946  
 947      /**
 948       * @return string|null
 949       */
 950  	public function execute() {
 951          if ( $this->getVar( '_SkipOptional' ) == 'skip' ) {
 952              $this->submitSkins();
 953              return 'skip';
 954          }
 955          if ( $this->parent->request->wasPosted() ) {
 956              if ( $this->submit() ) {
 957                  return 'continue';
 958              }
 959          }
 960  
 961          $emailwrapperStyle = $this->getVar( 'wgEnableEmail' ) ? '' : 'display: none';
 962          $this->startForm();
 963          $this->addHTML(
 964              # User Rights
 965              // getRadioSet() builds a set of labeled radio buttons.
 966              // For grep: The following messages are used as the item labels:
 967              // config-profile-wiki, config-profile-no-anon, config-profile-fishbowl, config-profile-private
 968              $this->parent->getRadioSet( array(
 969                  'var' => '_RightsProfile',
 970                  'label' => 'config-profile',
 971                  'itemLabelPrefix' => 'config-profile-',
 972                  'values' => array_keys( $this->parent->rightsProfiles ),
 973              ) ) .
 974              $this->parent->getInfoBox( wfMessage( 'config-profile-help' )->plain() ) .
 975  
 976              # Licensing
 977              // getRadioSet() builds a set of labeled radio buttons.
 978              // For grep: The following messages are used as the item labels:
 979              // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa,
 980              // config-license-cc-0, config-license-pd, config-license-gfdl,
 981              // config-license-none, config-license-cc-choose
 982              $this->parent->getRadioSet( array(
 983                  'var' => '_LicenseCode',
 984                  'label' => 'config-license',
 985                  'itemLabelPrefix' => 'config-license-',
 986                  'values' => array_keys( $this->parent->licenses ),
 987                  'commonAttribs' => array( 'class' => 'licenseRadio' ),
 988              ) ) .
 989              $this->getCCChooser() .
 990              $this->parent->getHelpBox( 'config-license-help' ) .
 991  
 992              # E-mail
 993              $this->getFieldSetStart( 'config-email-settings' ) .
 994              $this->parent->getCheckBox( array(
 995                  'var' => 'wgEnableEmail',
 996                  'label' => 'config-enable-email',
 997                  'attribs' => array( 'class' => 'showHideRadio', 'rel' => 'emailwrapper' ),
 998              ) ) .
 999              $this->parent->getHelpBox( 'config-enable-email-help' ) .
1000              "<div id=\"emailwrapper\" style=\"$emailwrapperStyle\">" .
1001              $this->parent->getTextBox( array(
1002                  'var' => 'wgPasswordSender',
1003                  'label' => 'config-email-sender'
1004              ) ) .
1005              $this->parent->getHelpBox( 'config-email-sender-help' ) .
1006              $this->parent->getCheckBox( array(
1007                  'var' => 'wgEnableUserEmail',
1008                  'label' => 'config-email-user',
1009              ) ) .
1010              $this->parent->getHelpBox( 'config-email-user-help' ) .
1011              $this->parent->getCheckBox( array(
1012                  'var' => 'wgEnotifUserTalk',
1013                  'label' => 'config-email-usertalk',
1014              ) ) .
1015              $this->parent->getHelpBox( 'config-email-usertalk-help' ) .
1016              $this->parent->getCheckBox( array(
1017                  'var' => 'wgEnotifWatchlist',
1018                  'label' => 'config-email-watchlist',
1019              ) ) .
1020              $this->parent->getHelpBox( 'config-email-watchlist-help' ) .
1021              $this->parent->getCheckBox( array(
1022                  'var' => 'wgEmailAuthentication',
1023                  'label' => 'config-email-auth',
1024              ) ) .
1025              $this->parent->getHelpBox( 'config-email-auth-help' ) .
1026              "</div>" .
1027              $this->getFieldSetEnd()
1028          );
1029  
1030          $skins = $this->parent->findExtensions( 'skins' );
1031          $skinHtml = $this->getFieldSetStart( 'config-skins' );
1032  
1033          if ( $skins ) {
1034              $skinNames = array_map( 'strtolower', $skins );
1035  
1036              $radioButtons = $this->parent->getRadioElements( array(
1037                  'var' => 'wgDefaultSkin',
1038                  'itemLabels' => array_fill_keys( $skinNames, 'config-skins-use-as-default' ),
1039                  'values' => $skinNames,
1040                  'value' => $this->getVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) ),
1041              ) );
1042  
1043              foreach ( $skins as $skin ) {
1044                  $skinHtml .=
1045                      '<div class="config-skins-item">' .
1046                      $this->parent->getCheckBox( array(
1047                          'var' => "skin-$skin",
1048                          'rawtext' => $skin,
1049                          'value' => $this->getVar( "skin-$skin", true ), // all found skins enabled by default
1050                      ) ) .
1051                      '<div class="config-skins-use-as-default">' . $radioButtons[strtolower( $skin )] . '</div>' .
1052                      '</div>';
1053              }
1054          } else {
1055              $skinHtml .= $this->parent->getWarningBox( wfMessage( 'config-skins-missing' )->plain() );
1056          }
1057  
1058          $skinHtml .= $this->parent->getHelpBox( 'config-skins-help' ) .
1059              $this->getFieldSetEnd();
1060          $this->addHTML( $skinHtml );
1061  
1062          $extensions = $this->parent->findExtensions();
1063  
1064          if ( $extensions ) {
1065              $extHtml = $this->getFieldSetStart( 'config-extensions' );
1066  
1067              foreach ( $extensions as $ext ) {
1068                  $extHtml .= $this->parent->getCheckBox( array(
1069                      'var' => "ext-$ext",
1070                      'rawtext' => $ext,
1071                  ) );
1072              }
1073  
1074              $extHtml .= $this->parent->getHelpBox( 'config-extensions-help' ) .
1075                  $this->getFieldSetEnd();
1076              $this->addHTML( $extHtml );
1077          }
1078  
1079          // Having / in paths in Windows looks funny :)
1080          $this->setVar( 'wgDeletedDirectory',
1081              str_replace(
1082                  '/', DIRECTORY_SEPARATOR,
1083                  $this->getVar( 'wgDeletedDirectory' )
1084              )
1085          );
1086  
1087          $uploadwrapperStyle = $this->getVar( 'wgEnableUploads' ) ? '' : 'display: none';
1088          $this->addHTML(
1089              # Uploading
1090              $this->getFieldSetStart( 'config-upload-settings' ) .
1091              $this->parent->getCheckBox( array(
1092                  'var' => 'wgEnableUploads',
1093                  'label' => 'config-upload-enable',
1094                  'attribs' => array( 'class' => 'showHideRadio', 'rel' => 'uploadwrapper' ),
1095                  'help' => $this->parent->getHelpBox( 'config-upload-help' )
1096              ) ) .
1097              '<div id="uploadwrapper" style="' . $uploadwrapperStyle . '">' .
1098              $this->parent->getTextBox( array(
1099                  'var' => 'wgDeletedDirectory',
1100                  'label' => 'config-upload-deleted',
1101                  'attribs' => array( 'dir' => 'ltr' ),
1102                  'help' => $this->parent->getHelpBox( 'config-upload-deleted-help' )
1103              ) ) .
1104              '</div>' .
1105              $this->parent->getTextBox( array(
1106                  'var' => 'wgLogo',
1107                  'label' => 'config-logo',
1108                  'attribs' => array( 'dir' => 'ltr' ),
1109                  'help' => $this->parent->getHelpBox( 'config-logo-help' )
1110              ) )
1111          );
1112          $this->addHTML(
1113              $this->parent->getCheckBox( array(
1114                  'var' => 'wgUseInstantCommons',
1115                  'label' => 'config-instantcommons',
1116                  'help' => $this->parent->getHelpBox( 'config-instantcommons-help' )
1117              ) ) .
1118              $this->getFieldSetEnd()
1119          );
1120  
1121          $caches = array( 'none' );
1122          if ( count( $this->getVar( '_Caches' ) ) ) {
1123              $caches[] = 'accel';
1124          }
1125          $caches[] = 'memcached';
1126  
1127          // We'll hide/show this on demand when the value changes, see config.js.
1128          $cacheval = $this->getVar( 'wgMainCacheType' );
1129          if ( !$cacheval ) {
1130              // We need to set a default here; but don't hardcode it
1131              // or we lose it every time we reload the page for validation
1132              // or going back!
1133              $cacheval = 'none';
1134          }
1135          $hidden = ( $cacheval == 'memcached' ) ? '' : 'display: none';
1136          $this->addHTML(
1137              # Advanced settings
1138              $this->getFieldSetStart( 'config-advanced-settings' ) .
1139              # Object cache settings
1140              // getRadioSet() builds a set of labeled radio buttons.
1141              // For grep: The following messages are used as the item labels:
1142              // config-cache-none, config-cache-accel, config-cache-memcached
1143              $this->parent->getRadioSet( array(
1144                  'var' => 'wgMainCacheType',
1145                  'label' => 'config-cache-options',
1146                  'itemLabelPrefix' => 'config-cache-',
1147                  'values' => $caches,
1148                  'value' => $cacheval,
1149              ) ) .
1150              $this->parent->getHelpBox( 'config-cache-help' ) .
1151              "<div id=\"config-memcachewrapper\" style=\"$hidden\">" .
1152              $this->parent->getTextArea( array(
1153                  'var' => '_MemCachedServers',
1154                  'label' => 'config-memcached-servers',
1155                  'help' => $this->parent->getHelpBox( 'config-memcached-help' )
1156              ) ) .
1157              '</div>' .
1158              $this->getFieldSetEnd()
1159          );
1160          $this->endForm();
1161  
1162          return null;
1163      }
1164  
1165      /**
1166       * @return string
1167       */
1168  	public function getCCPartnerUrl() {
1169          $server = $this->getVar( 'wgServer' );
1170          $exitUrl = $server . $this->parent->getUrl( array(
1171              'page' => 'Options',
1172              'SubmitCC' => 'indeed',
1173              'config__LicenseCode' => 'cc',
1174              'config_wgRightsUrl' => '[license_url]',
1175              'config_wgRightsText' => '[license_name]',
1176              'config_wgRightsIcon' => '[license_button]',
1177          ) );
1178          $styleUrl = $server . dirname( dirname( $this->parent->getUrl() ) ) .
1179              '/mw-config/config-cc.css';
1180          $iframeUrl = 'http://creativecommons.org/license/?' .
1181              wfArrayToCgi( array(
1182                  'partner' => 'MediaWiki',
1183                  'exit_url' => $exitUrl,
1184                  'lang' => $this->getVar( '_UserLang' ),
1185                  'stylesheet' => $styleUrl,
1186              ) );
1187  
1188          return $iframeUrl;
1189      }
1190  
1191      /**
1192       * @return string
1193       */
1194  	public function getCCChooser() {
1195          $iframeAttribs = array(
1196              'class' => 'config-cc-iframe',
1197              'name' => 'config-cc-iframe',
1198              'id' => 'config-cc-iframe',
1199              'frameborder' => 0,
1200              'width' => '100%',
1201              'height' => '100%',
1202          );
1203          if ( $this->getVar( '_CCDone' ) ) {
1204              $iframeAttribs['src'] = $this->parent->getUrl( array( 'ShowCC' => 'yes' ) );
1205          } else {
1206              $iframeAttribs['src'] = $this->getCCPartnerUrl();
1207          }
1208          $wrapperStyle = ( $this->getVar( '_LicenseCode' ) == 'cc-choose' ) ? '' : 'display: none';
1209  
1210          return "<div class=\"config-cc-wrapper\" id=\"config-cc-wrapper\" style=\"$wrapperStyle\">\n" .
1211              Html::element( 'iframe', $iframeAttribs, '', false /* not short */ ) .
1212              "</div>\n";
1213      }
1214  
1215      /**
1216       * @return string
1217       */
1218  	public function getCCDoneBox() {
1219          $js = "parent.document.getElementById('config-cc-wrapper').style.height = '$1';";
1220          // If you change this height, also change it in config.css
1221          $expandJs = str_replace( '$1', '54em', $js );
1222          $reduceJs = str_replace( '$1', '70px', $js );
1223  
1224          return '<p>' .
1225              Html::element( 'img', array( 'src' => $this->getVar( 'wgRightsIcon' ) ) ) .
1226              '&#160;&#160;' .
1227              htmlspecialchars( $this->getVar( 'wgRightsText' ) ) .
1228              "</p>\n" .
1229              "<p style=\"text-align: center;\">" .
1230              Html::element( 'a',
1231                  array(
1232                      'href' => $this->getCCPartnerUrl(),
1233                      'onclick' => $expandJs,
1234                  ),
1235                  wfMessage( 'config-cc-again' )->text()
1236              ) .
1237              "</p>\n" .
1238              "<script>\n" .
1239              # Reduce the wrapper div height
1240              htmlspecialchars( $reduceJs ) .
1241              "\n" .
1242              "</script>\n";
1243      }
1244  
1245  	public function submitCC() {
1246          $newValues = $this->parent->setVarsFromRequest(
1247              array( 'wgRightsUrl', 'wgRightsText', 'wgRightsIcon' ) );
1248          if ( count( $newValues ) != 3 ) {
1249              $this->parent->showError( 'config-cc-error' );
1250  
1251              return;
1252          }
1253          $this->setVar( '_CCDone', true );
1254          $this->addHTML( $this->getCCDoneBox() );
1255      }
1256  
1257      /**
1258       * If the user skips this installer page, we still need to set up the default skins, but ignore
1259       * everything else.
1260       *
1261       * @return bool
1262       */
1263  	public function submitSkins() {
1264          $skins = $this->parent->findExtensions( 'skins' );
1265          $this->parent->setVar( '_Skins', $skins );
1266  
1267          if ( $skins ) {
1268              $skinNames = array_map( 'strtolower', $skins );
1269              $this->parent->setVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) );
1270          }
1271  
1272          return true;
1273      }
1274  
1275      /**
1276       * @return bool
1277       */
1278  	public function submit() {
1279          $this->parent->setVarsFromRequest( array( '_RightsProfile', '_LicenseCode',
1280              'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads', 'wgLogo',
1281              'wgEnableUserEmail', 'wgEnotifUserTalk', 'wgEnotifWatchlist',
1282              'wgEmailAuthentication', 'wgMainCacheType', '_MemCachedServers',
1283              'wgUseInstantCommons', 'wgDefaultSkin' ) );
1284  
1285          $retVal = true;
1286  
1287          if ( !array_key_exists( $this->getVar( '_RightsProfile' ), $this->parent->rightsProfiles )
1288          ) {
1289              reset( $this->parent->rightsProfiles );
1290              $this->setVar( '_RightsProfile', key( $this->parent->rightsProfiles ) );
1291          }
1292  
1293          $code = $this->getVar( '_LicenseCode' );
1294          if ( $code == 'cc-choose' ) {
1295              if ( !$this->getVar( '_CCDone' ) ) {
1296                  $this->parent->showError( 'config-cc-not-chosen' );
1297                  $retVal = false;
1298              }
1299          } elseif ( array_key_exists( $code, $this->parent->licenses ) ) {
1300              // Messages:
1301              // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa,
1302              // config-license-cc-0, config-license-pd, config-license-gfdl, config-license-none,
1303              // config-license-cc-choose
1304              $entry = $this->parent->licenses[$code];
1305              if ( isset( $entry['text'] ) ) {
1306                  $this->setVar( 'wgRightsText', $entry['text'] );
1307              } else {
1308                  $this->setVar( 'wgRightsText', wfMessage( 'config-license-' . $code )->text() );
1309              }
1310              $this->setVar( 'wgRightsUrl', $entry['url'] );
1311              $this->setVar( 'wgRightsIcon', $entry['icon'] );
1312          } else {
1313              $this->setVar( 'wgRightsText', '' );
1314              $this->setVar( 'wgRightsUrl', '' );
1315              $this->setVar( 'wgRightsIcon', '' );
1316          }
1317  
1318          $skinsAvailable = $this->parent->findExtensions( 'skins' );
1319          $skinsToInstall = array();
1320          foreach ( $skinsAvailable as $skin ) {
1321              $this->parent->setVarsFromRequest( array( "skin-$skin" ) );
1322              if ( $this->getVar( "skin-$skin" ) ) {
1323                  $skinsToInstall[] = $skin;
1324              }
1325          }
1326          $this->parent->setVar( '_Skins', $skinsToInstall );
1327  
1328          if ( !$skinsToInstall && $skinsAvailable ) {
1329              $this->parent->showError( 'config-skins-must-enable-some' );
1330              $retVal = false;
1331          }
1332          $defaultSkin = $this->getVar( 'wgDefaultSkin' );
1333          $skinsToInstallLowercase = array_map( 'strtolower', $skinsToInstall );
1334          if ( $skinsToInstall && array_search( $defaultSkin, $skinsToInstallLowercase ) === false ) {
1335              $this->parent->showError( 'config-skins-must-enable-default' );
1336              $retVal = false;
1337          }
1338  
1339          $extsAvailable = $this->parent->findExtensions();
1340          $extsToInstall = array();
1341          foreach ( $extsAvailable as $ext ) {
1342              $this->parent->setVarsFromRequest( array( "ext-$ext" ) );
1343              if ( $this->getVar( "ext-$ext" ) ) {
1344                  $extsToInstall[] = $ext;
1345              }
1346          }
1347          $this->parent->setVar( '_Extensions', $extsToInstall );
1348  
1349          if ( $this->getVar( 'wgMainCacheType' ) == 'memcached' ) {
1350              $memcServers = explode( "\n", $this->getVar( '_MemCachedServers' ) );
1351              if ( !$memcServers ) {
1352                  $this->parent->showError( 'config-memcache-needservers' );
1353                  $retVal = false;
1354              }
1355  
1356              foreach ( $memcServers as $server ) {
1357                  $memcParts = explode( ":", $server, 2 );
1358                  if ( !isset( $memcParts[0] )
1359                      || ( !IP::isValid( $memcParts[0] )
1360                          && ( gethostbyname( $memcParts[0] ) == $memcParts[0] ) )
1361                  ) {
1362                      $this->parent->showError( 'config-memcache-badip', $memcParts[0] );
1363                      $retVal = false;
1364                  } elseif ( !isset( $memcParts[1] ) ) {
1365                      $this->parent->showError( 'config-memcache-noport', $memcParts[0] );
1366                      $retVal = false;
1367                  } elseif ( $memcParts[1] < 1 || $memcParts[1] > 65535 ) {
1368                      $this->parent->showError( 'config-memcache-badport', 1, 65535 );
1369                      $retVal = false;
1370                  }
1371              }
1372          }
1373  
1374          return $retVal;
1375      }
1376  
1377  }
1378  
1379  class WebInstallerInstall extends WebInstallerPage {
1380  
1381      /**
1382       * @return bool Always true.
1383       */
1384  	public function isSlow() {
1385          return true;
1386      }
1387  
1388      /**
1389       * @return string|bool
1390       */
1391  	public function execute() {
1392          if ( $this->getVar( '_UpgradeDone' ) ) {
1393              return 'skip';
1394          } elseif ( $this->getVar( '_InstallDone' ) ) {
1395              return 'continue';
1396          } elseif ( $this->parent->request->wasPosted() ) {
1397              $this->startForm();
1398              $this->addHTML( "<ul>" );
1399              $results = $this->parent->performInstallation(
1400                  array( $this, 'startStage' ),
1401                  array( $this, 'endStage' )
1402              );
1403              $this->addHTML( "</ul>" );
1404              // PerformInstallation bails on a fatal, so make sure the last item
1405              // completed before giving 'next.' Likewise, only provide back on failure
1406              $lastStep = end( $results );
1407              $continue = $lastStep->isOK() ? 'continue' : false;
1408              $back = $lastStep->isOK() ? false : 'back';
1409              $this->endForm( $continue, $back );
1410          } else {
1411              $this->startForm();
1412              $this->addHTML( $this->parent->getInfoBox( wfMessage( 'config-install-begin' )->plain() ) );
1413              $this->endForm();
1414          }
1415  
1416          return true;
1417      }
1418  
1419      /**
1420       * @param string $step
1421       */
1422  	public function startStage( $step ) {
1423          // Messages: config-install-database, config-install-tables, config-install-interwiki,
1424          // config-install-stats, config-install-keys, config-install-sysop, config-install-mainpage
1425          $this->addHTML( "<li>" . wfMessage( "config-install-$step" )->escaped() .
1426              wfMessage( 'ellipsis' )->escaped() );
1427  
1428          if ( $step == 'extension-tables' ) {
1429              $this->startLiveBox();
1430          }
1431      }
1432  
1433      /**
1434       * @param string $step
1435       * @param Status $status
1436       */
1437  	public function endStage( $step, $status ) {
1438          if ( $step == 'extension-tables' ) {
1439              $this->endLiveBox();
1440          }
1441          $msg = $status->isOk() ? 'config-install-step-done' : 'config-install-step-failed';
1442          $html = wfMessage( 'word-separator' )->escaped() . wfMessage( $msg )->escaped();
1443          if ( !$status->isOk() ) {
1444              $html = "<span class=\"error\">$html</span>";
1445          }
1446          $this->addHTML( $html . "</li>\n" );
1447          if ( !$status->isGood() ) {
1448              $this->parent->showStatusBox( $status );
1449          }
1450      }
1451  
1452  }
1453  
1454  class WebInstallerComplete extends WebInstallerPage {
1455  
1456  	public function execute() {
1457          // Pop up a dialog box, to make it difficult for the user to forget
1458          // to download the file
1459          $lsUrl = $this->getVar( 'wgServer' ) . $this->parent->getURL( array( 'localsettings' => 1 ) );
1460          if ( isset( $_SERVER['HTTP_USER_AGENT'] ) &&
1461              strpos( $_SERVER['HTTP_USER_AGENT'], 'MSIE' ) !== false
1462          ) {
1463              // JS appears to be the only method that works consistently with IE7+
1464              $this->addHtml( "\n<script>jQuery( function () { document.location = " .
1465                  Xml::encodeJsVar( $lsUrl ) . "; } );</script>\n" );
1466          } else {
1467              $this->parent->request->response()->header( "Refresh: 0;url=$lsUrl" );
1468          }
1469  
1470          $this->startForm();
1471          $this->parent->disableLinkPopups();
1472          $this->addHTML(
1473              $this->parent->getInfoBox(
1474                  wfMessage( 'config-install-done',
1475                      $lsUrl,
1476                      $this->getVar( 'wgServer' ) .
1477                      $this->getVar( 'wgScriptPath' ) . '/index' .
1478                      $this->getVar( 'wgScriptExtension' ),
1479                      '<downloadlink/>'
1480                  )->plain(), 'tick-32.png'
1481              )
1482          );
1483          $this->addHTML( $this->parent->getInfoBox(
1484              wfMessage( 'config-extension-link' )->text() ) );
1485  
1486          $this->parent->restoreLinkPopups();
1487          $this->endForm( false, false );
1488      }
1489  
1490  }
1491  
1492  class WebInstallerRestart extends WebInstallerPage {
1493  
1494      /**
1495       * @return string|null
1496       */
1497  	public function execute() {
1498          $r = $this->parent->request;
1499          if ( $r->wasPosted() ) {
1500              $really = $r->getVal( 'submit-restart' );
1501              if ( $really ) {
1502                  $this->parent->reset();
1503              }
1504  
1505              return 'continue';
1506          }
1507  
1508          $this->startForm();
1509          $s = $this->parent->getWarningBox( wfMessage( 'config-help-restart' )->plain() );
1510          $this->addHTML( $s );
1511          $this->endForm( 'restart' );
1512  
1513          return null;
1514      }
1515  
1516  }
1517  
1518  abstract class WebInstallerDocument extends WebInstallerPage {
1519  
1520      /**
1521       * @return string
1522       */
1523      abstract protected function getFileName();
1524  
1525  	public function execute() {
1526          $text = $this->getFileContents();
1527          $text = InstallDocFormatter::format( $text );
1528          $this->parent->output->addWikiText( $text );
1529          $this->startForm();
1530          $this->endForm( false );
1531      }
1532  
1533      /**
1534       * @return string
1535       */
1536  	public function getFileContents() {
1537          $file = __DIR__ . '/../../' . $this->getFileName();
1538          if ( !file_exists( $file ) ) {
1539              return wfMessage( 'config-nofile', $file )->plain();
1540          }
1541  
1542          return file_get_contents( $file );
1543      }
1544  
1545  }
1546  
1547  class WebInstallerReadme extends WebInstallerDocument {
1548  
1549      /**
1550       * @return string
1551       */
1552  	protected function getFileName() {
1553          return 'README';
1554      }
1555  
1556  }
1557  
1558  class WebInstallerReleaseNotes extends WebInstallerDocument {
1559  
1560      /**
1561       * @throws MWException
1562       * @return string
1563       */
1564  	protected function getFileName() {
1565          global $wgVersion;
1566  
1567          if ( !preg_match( '/^(\d+)\.(\d+).*/i', $wgVersion, $result ) ) {
1568              throw new MWException( 'Variable $wgVersion has an invalid value.' );
1569          }
1570  
1571          return 'RELEASE-NOTES-' . $result[1] . '.' . $result[2];
1572      }
1573  
1574  }
1575  
1576  class WebInstallerUpgradeDoc extends WebInstallerDocument {
1577  
1578      /**
1579       * @return string
1580       */
1581  	protected function getFileName() {
1582          return 'UPGRADE';
1583      }
1584  
1585  }
1586  
1587  class WebInstallerCopying extends WebInstallerDocument {
1588  
1589      /**
1590       * @return string
1591       */
1592  	protected function getFileName() {
1593          return 'COPYING';
1594      }
1595  
1596  }


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