[ Index ]

PHP Cross Reference of MediaWiki-1.24.0

title

Body

[close]

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

   1  <?php
   2  /**
   3   * Core installer web interface.
   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   * Class for the core installer web interface.
  26   *
  27   * @ingroup Deployment
  28   * @since 1.17
  29   */
  30  class WebInstaller extends Installer {
  31  
  32      /**
  33       * @var WebInstallerOutput
  34       */
  35      public $output;
  36  
  37      /**
  38       * WebRequest object.
  39       *
  40       * @var WebRequest
  41       */
  42      public $request;
  43  
  44      /**
  45       * Cached session array.
  46       *
  47       * @var array[]
  48       */
  49      protected $session;
  50  
  51      /**
  52       * Captured PHP error text. Temporary.
  53       *
  54       * @var string[]
  55       */
  56      protected $phpErrors;
  57  
  58      /**
  59       * The main sequence of page names. These will be displayed in turn.
  60       *
  61       * To add a new installer page:
  62       *    * Add it to this WebInstaller::$pageSequence property
  63       *    * Add a "config-page-<name>" message
  64       *    * Add a "WebInstaller<name>" class
  65       *
  66       * @var string[]
  67       */
  68      public $pageSequence = array(
  69          'Language',
  70          'ExistingWiki',
  71          'Welcome',
  72          'DBConnect',
  73          'Upgrade',
  74          'DBSettings',
  75          'Name',
  76          'Options',
  77          'Install',
  78          'Complete',
  79      );
  80  
  81      /**
  82       * Out of sequence pages, selectable by the user at any time.
  83       *
  84       * @var string[]
  85       */
  86      protected $otherPages = array(
  87          'Restart',
  88          'Readme',
  89          'ReleaseNotes',
  90          'Copying',
  91          'UpgradeDoc', // Can't use Upgrade due to Upgrade step
  92      );
  93  
  94      /**
  95       * Array of pages which have declared that they have been submitted, have validated
  96       * their input, and need no further processing.
  97       *
  98       * @var bool[]
  99       */
 100      protected $happyPages;
 101  
 102      /**
 103       * List of "skipped" pages. These are pages that will automatically continue
 104       * to the next page on any GET request. To avoid breaking the "back" button,
 105       * they need to be skipped during a back operation.
 106       *
 107       * @var bool[]
 108       */
 109      protected $skippedPages;
 110  
 111      /**
 112       * Flag indicating that session data may have been lost.
 113       *
 114       * @var bool
 115       */
 116      public $showSessionWarning = false;
 117  
 118      /**
 119       * Numeric index of the page we're on
 120       *
 121       * @var int
 122       */
 123      protected $tabIndex = 1;
 124  
 125      /**
 126       * Name of the page we're on
 127       *
 128       * @var string
 129       */
 130      protected $currentPageName;
 131  
 132      /**
 133       * Constructor.
 134       *
 135       * @param WebRequest $request
 136       */
 137  	public function __construct( WebRequest $request ) {
 138          parent::__construct();
 139          $this->output = new WebInstallerOutput( $this );
 140          $this->request = $request;
 141  
 142          // Add parser hooks
 143          global $wgParser;
 144          $wgParser->setHook( 'downloadlink', array( $this, 'downloadLinkHook' ) );
 145          $wgParser->setHook( 'doclink', array( $this, 'docLink' ) );
 146      }
 147  
 148      /**
 149       * Main entry point.
 150       *
 151       * @param array[] $session Initial session array
 152       *
 153       * @return array[] New session array
 154       */
 155  	public function execute( array $session ) {
 156          $this->session = $session;
 157  
 158          if ( isset( $session['settings'] ) ) {
 159              $this->settings = $session['settings'] + $this->settings;
 160          }
 161  
 162          $this->exportVars();
 163          $this->setupLanguage();
 164  
 165          if ( ( $this->getVar( '_InstallDone' ) || $this->getVar( '_UpgradeDone' ) )
 166              && $this->request->getVal( 'localsettings' )
 167          ) {
 168              $this->request->response()->header( 'Content-type: application/x-httpd-php' );
 169              $this->request->response()->header(
 170                  'Content-Disposition: attachment; filename="LocalSettings.php"'
 171              );
 172  
 173              $ls = InstallerOverrides::getLocalSettingsGenerator( $this );
 174              $rightsProfile = $this->rightsProfiles[$this->getVar( '_RightsProfile' )];
 175              foreach ( $rightsProfile as $group => $rightsArr ) {
 176                  $ls->setGroupRights( $group, $rightsArr );
 177              }
 178              echo $ls->getText();
 179  
 180              return $this->session;
 181          }
 182  
 183          $isCSS = $this->request->getVal( 'css' );
 184          if ( $isCSS ) {
 185              $this->outputCss();
 186              return $this->session;
 187          }
 188  
 189          if ( isset( $session['happyPages'] ) ) {
 190              $this->happyPages = $session['happyPages'];
 191          } else {
 192              $this->happyPages = array();
 193          }
 194  
 195          if ( isset( $session['skippedPages'] ) ) {
 196              $this->skippedPages = $session['skippedPages'];
 197          } else {
 198              $this->skippedPages = array();
 199          }
 200  
 201          $lowestUnhappy = $this->getLowestUnhappy();
 202  
 203          # Special case for Creative Commons partner chooser box.
 204          if ( $this->request->getVal( 'SubmitCC' ) ) {
 205              $page = $this->getPageByName( 'Options' );
 206              $this->output->useShortHeader();
 207              $this->output->allowFrames();
 208              $page->submitCC();
 209  
 210              return $this->finish();
 211          }
 212  
 213          if ( $this->request->getVal( 'ShowCC' ) ) {
 214              $page = $this->getPageByName( 'Options' );
 215              $this->output->useShortHeader();
 216              $this->output->allowFrames();
 217              $this->output->addHTML( $page->getCCDoneBox() );
 218  
 219              return $this->finish();
 220          }
 221  
 222          # Get the page name.
 223          $pageName = $this->request->getVal( 'page' );
 224  
 225          if ( in_array( $pageName, $this->otherPages ) ) {
 226              # Out of sequence
 227              $pageId = false;
 228              $page = $this->getPageByName( $pageName );
 229          } else {
 230              # Main sequence
 231              if ( !$pageName || !in_array( $pageName, $this->pageSequence ) ) {
 232                  $pageId = $lowestUnhappy;
 233              } else {
 234                  $pageId = array_search( $pageName, $this->pageSequence );
 235              }
 236  
 237              # If necessary, move back to the lowest-numbered unhappy page
 238              if ( $pageId > $lowestUnhappy ) {
 239                  $pageId = $lowestUnhappy;
 240                  if ( $lowestUnhappy == 0 ) {
 241                      # Knocked back to start, possible loss of session data.
 242                      $this->showSessionWarning = true;
 243                  }
 244              }
 245  
 246              $pageName = $this->pageSequence[$pageId];
 247              $page = $this->getPageByName( $pageName );
 248          }
 249  
 250          # If a back button was submitted, go back without submitting the form data.
 251          if ( $this->request->wasPosted() && $this->request->getBool( 'submit-back' ) ) {
 252              if ( $this->request->getVal( 'lastPage' ) ) {
 253                  $nextPage = $this->request->getVal( 'lastPage' );
 254              } elseif ( $pageId !== false ) {
 255                  # Main sequence page
 256                  # Skip the skipped pages
 257                  $nextPageId = $pageId;
 258  
 259                  do {
 260                      $nextPageId--;
 261                      $nextPage = $this->pageSequence[$nextPageId];
 262                  } while ( isset( $this->skippedPages[$nextPage] ) );
 263              } else {
 264                  $nextPage = $this->pageSequence[$lowestUnhappy];
 265              }
 266  
 267              $this->output->redirect( $this->getUrl( array( 'page' => $nextPage ) ) );
 268  
 269              return $this->finish();
 270          }
 271  
 272          # Execute the page.
 273          $this->currentPageName = $page->getName();
 274          $this->startPageWrapper( $pageName );
 275  
 276          if ( $page->isSlow() ) {
 277              $this->disableTimeLimit();
 278          }
 279  
 280          $result = $page->execute();
 281  
 282          $this->endPageWrapper();
 283  
 284          if ( $result == 'skip' ) {
 285              # Page skipped without explicit submission.
 286              # Skip it when we click "back" so that we don't just go forward again.
 287              $this->skippedPages[$pageName] = true;
 288              $result = 'continue';
 289          } else {
 290              unset( $this->skippedPages[$pageName] );
 291          }
 292  
 293          # If it was posted, the page can request a continue to the next page.
 294          if ( $result === 'continue' && !$this->output->headerDone() ) {
 295              if ( $pageId !== false ) {
 296                  $this->happyPages[$pageId] = true;
 297              }
 298  
 299              $lowestUnhappy = $this->getLowestUnhappy();
 300  
 301              if ( $this->request->getVal( 'lastPage' ) ) {
 302                  $nextPage = $this->request->getVal( 'lastPage' );
 303              } elseif ( $pageId !== false ) {
 304                  $nextPage = $this->pageSequence[$pageId + 1];
 305              } else {
 306                  $nextPage = $this->pageSequence[$lowestUnhappy];
 307              }
 308  
 309              if ( array_search( $nextPage, $this->pageSequence ) > $lowestUnhappy ) {
 310                  $nextPage = $this->pageSequence[$lowestUnhappy];
 311              }
 312  
 313              $this->output->redirect( $this->getUrl( array( 'page' => $nextPage ) ) );
 314          }
 315  
 316          return $this->finish();
 317      }
 318  
 319      /**
 320       * Find the next page in sequence that hasn't been completed
 321       * @return int
 322       */
 323  	public function getLowestUnhappy() {
 324          if ( count( $this->happyPages ) == 0 ) {
 325              return 0;
 326          } else {
 327              return max( array_keys( $this->happyPages ) ) + 1;
 328          }
 329      }
 330  
 331      /**
 332       * Start the PHP session. This may be called before execute() to start the PHP session.
 333       *
 334       * @throws Exception
 335       * @return bool
 336       */
 337  	public function startSession() {
 338          if ( wfIniGetBool( 'session.auto_start' ) || session_id() ) {
 339              // Done already
 340              return true;
 341          }
 342  
 343          $this->phpErrors = array();
 344          set_error_handler( array( $this, 'errorHandler' ) );
 345          try {
 346              session_start();
 347          } catch ( Exception $e ) {
 348              restore_error_handler();
 349              throw $e;
 350          }
 351          restore_error_handler();
 352  
 353          if ( $this->phpErrors ) {
 354              return false;
 355          }
 356  
 357          return true;
 358      }
 359  
 360      /**
 361       * Get a hash of data identifying this MW installation.
 362       *
 363       * This is used by mw-config/index.php to prevent multiple installations of MW
 364       * on the same cookie domain from interfering with each other.
 365       *
 366       * @return string
 367       */
 368  	public function getFingerprint() {
 369          // Get the base URL of the installation
 370          $url = $this->request->getFullRequestURL();
 371          if ( preg_match( '!^(.*\?)!', $url, $m ) ) {
 372              // Trim query string
 373              $url = $m[1];
 374          }
 375          if ( preg_match( '!^(.*)/[^/]*/[^/]*$!', $url, $m ) ) {
 376              // This... seems to try to get the base path from
 377              // the /mw-config/index.php. Kinda scary though?
 378              $url = $m[1];
 379          }
 380  
 381          return md5( serialize( array(
 382              'local path' => dirname( __DIR__ ),
 383              'url' => $url,
 384              'version' => $GLOBALS['wgVersion']
 385          ) ) );
 386      }
 387  
 388      /**
 389       * Show an error message in a box. Parameters are like wfMessage().
 390       * @param string $msg
 391       */
 392  	public function showError( $msg /*...*/ ) {
 393          $args = func_get_args();
 394          array_shift( $args );
 395          $args = array_map( 'htmlspecialchars', $args );
 396          $msg = wfMessage( $msg, $args )->useDatabase( false )->plain();
 397          $this->output->addHTML( $this->getErrorBox( $msg ) );
 398      }
 399  
 400      /**
 401       * Temporary error handler for session start debugging.
 402       *
 403       * @param int $errno Unused
 404       * @param string $errstr
 405       */
 406  	public function errorHandler( $errno, $errstr ) {
 407          $this->phpErrors[] = $errstr;
 408      }
 409  
 410      /**
 411       * Clean up from execute()
 412       *
 413       * @return array[]
 414       */
 415  	public function finish() {
 416          $this->output->output();
 417  
 418          $this->session['happyPages'] = $this->happyPages;
 419          $this->session['skippedPages'] = $this->skippedPages;
 420          $this->session['settings'] = $this->settings;
 421  
 422          return $this->session;
 423      }
 424  
 425      /**
 426       * We're restarting the installation, reset the session, happyPages, etc
 427       */
 428  	public function reset() {
 429          $this->session = array();
 430          $this->happyPages = array();
 431          $this->settings = array();
 432      }
 433  
 434      /**
 435       * Get a URL for submission back to the same script.
 436       *
 437       * @param string[] $query
 438       *
 439       * @return string
 440       */
 441  	public function getUrl( $query = array() ) {
 442          $url = $this->request->getRequestURL();
 443          # Remove existing query
 444          $url = preg_replace( '/\?.*$/', '', $url );
 445  
 446          if ( $query ) {
 447              $url .= '?' . wfArrayToCgi( $query );
 448          }
 449  
 450          return $url;
 451      }
 452  
 453      /**
 454       * Get a WebInstallerPage by name.
 455       *
 456       * @param string $pageName
 457       * @return WebInstallerPage
 458       */
 459  	public function getPageByName( $pageName ) {
 460          $pageClass = 'WebInstaller' . $pageName;
 461  
 462          return new $pageClass( $this );
 463      }
 464  
 465      /**
 466       * Get a session variable.
 467       *
 468       * @param string $name
 469       * @param array $default
 470       *
 471       * @return array
 472       */
 473  	public function getSession( $name, $default = null ) {
 474          if ( !isset( $this->session[$name] ) ) {
 475              return $default;
 476          } else {
 477              return $this->session[$name];
 478          }
 479      }
 480  
 481      /**
 482       * Set a session variable.
 483       *
 484       * @param string $name Key for the variable
 485       * @param mixed $value
 486       */
 487  	public function setSession( $name, $value ) {
 488          $this->session[$name] = $value;
 489      }
 490  
 491      /**
 492       * Get the next tabindex attribute value.
 493       *
 494       * @return int
 495       */
 496  	public function nextTabIndex() {
 497          return $this->tabIndex++;
 498      }
 499  
 500      /**
 501       * Initializes language-related variables.
 502       */
 503  	public function setupLanguage() {
 504          global $wgLang, $wgContLang, $wgLanguageCode;
 505  
 506          if ( $this->getSession( 'test' ) === null && !$this->request->wasPosted() ) {
 507              $wgLanguageCode = $this->getAcceptLanguage();
 508              $wgLang = $wgContLang = Language::factory( $wgLanguageCode );
 509              $this->setVar( 'wgLanguageCode', $wgLanguageCode );
 510              $this->setVar( '_UserLang', $wgLanguageCode );
 511          } else {
 512              $wgLanguageCode = $this->getVar( 'wgLanguageCode' );
 513              $wgContLang = Language::factory( $wgLanguageCode );
 514          }
 515      }
 516  
 517      /**
 518       * Retrieves MediaWiki language from Accept-Language HTTP header.
 519       *
 520       * @return string
 521       */
 522  	public function getAcceptLanguage() {
 523          global $wgLanguageCode, $wgRequest;
 524  
 525          $mwLanguages = Language::fetchLanguageNames();
 526          $headerLanguages = array_keys( $wgRequest->getAcceptLang() );
 527  
 528          foreach ( $headerLanguages as $lang ) {
 529              if ( isset( $mwLanguages[$lang] ) ) {
 530                  return $lang;
 531              }
 532          }
 533  
 534          return $wgLanguageCode;
 535      }
 536  
 537      /**
 538       * Called by execute() before page output starts, to show a page list.
 539       *
 540       * @param string $currentPageName
 541       */
 542  	private function startPageWrapper( $currentPageName ) {
 543          $s = "<div class=\"config-page-wrapper\">\n";
 544          $s .= "<div class=\"config-page\">\n";
 545          $s .= "<div class=\"config-page-list\"><ul>\n";
 546          $lastHappy = -1;
 547  
 548          foreach ( $this->pageSequence as $id => $pageName ) {
 549              $happy = !empty( $this->happyPages[$id] );
 550              $s .= $this->getPageListItem(
 551                  $pageName,
 552                  $happy || $lastHappy == $id - 1,
 553                  $currentPageName
 554              );
 555  
 556              if ( $happy ) {
 557                  $lastHappy = $id;
 558              }
 559          }
 560  
 561          $s .= "</ul><br/><ul>\n";
 562          $s .= $this->getPageListItem( 'Restart', true, $currentPageName );
 563          // End list pane
 564          $s .= "</ul></div>\n";
 565  
 566          // Messages:
 567          // config-page-language, config-page-welcome, config-page-dbconnect, config-page-upgrade,
 568          // config-page-dbsettings, config-page-name, config-page-options, config-page-install,
 569          // config-page-complete, config-page-restart, config-page-readme, config-page-releasenotes,
 570          // config-page-copying, config-page-upgradedoc, config-page-existingwiki
 571          $s .= Html::element( 'h2', array(),
 572              wfMessage( 'config-page-' . strtolower( $currentPageName ) )->text() );
 573  
 574          $this->output->addHTMLNoFlush( $s );
 575      }
 576  
 577      /**
 578       * Get a list item for the page list.
 579       *
 580       * @param string $pageName
 581       * @param bool $enabled
 582       * @param string $currentPageName
 583       *
 584       * @return string
 585       */
 586  	private function getPageListItem( $pageName, $enabled, $currentPageName ) {
 587          $s = "<li class=\"config-page-list-item\">";
 588  
 589          // Messages:
 590          // config-page-language, config-page-welcome, config-page-dbconnect, config-page-upgrade,
 591          // config-page-dbsettings, config-page-name, config-page-options, config-page-install,
 592          // config-page-complete, config-page-restart, config-page-readme, config-page-releasenotes,
 593          // config-page-copying, config-page-upgradedoc, config-page-existingwiki
 594          $name = wfMessage( 'config-page-' . strtolower( $pageName ) )->text();
 595  
 596          if ( $enabled ) {
 597              $query = array( 'page' => $pageName );
 598  
 599              if ( !in_array( $pageName, $this->pageSequence ) ) {
 600                  if ( in_array( $currentPageName, $this->pageSequence ) ) {
 601                      $query['lastPage'] = $currentPageName;
 602                  }
 603  
 604                  $link = Html::element( 'a',
 605                      array(
 606                          'href' => $this->getUrl( $query )
 607                      ),
 608                      $name
 609                  );
 610              } else {
 611                  $link = htmlspecialchars( $name );
 612              }
 613  
 614              if ( $pageName == $currentPageName ) {
 615                  $s .= "<span class=\"config-page-current\">$link</span>";
 616              } else {
 617                  $s .= $link;
 618              }
 619          } else {
 620              $s .= Html::element( 'span',
 621                  array(
 622                      'class' => 'config-page-disabled'
 623                  ),
 624                  $name
 625              );
 626          }
 627  
 628          $s .= "</li>\n";
 629  
 630          return $s;
 631      }
 632  
 633      /**
 634       * Output some stuff after a page is finished.
 635       */
 636  	private function endPageWrapper() {
 637          $this->output->addHTMLNoFlush(
 638              "<div class=\"visualClear\"></div>\n" .
 639              "</div>\n" .
 640              "<div class=\"visualClear\"></div>\n" .
 641              "</div>" );
 642      }
 643  
 644      /**
 645       * Get HTML for an error box with an icon.
 646       *
 647       * @param string $text Wikitext, get this with wfMessage()->plain()
 648       *
 649       * @return string
 650       */
 651  	public function getErrorBox( $text ) {
 652          return $this->getInfoBox( $text, 'critical-32.png', 'config-error-box' );
 653      }
 654  
 655      /**
 656       * Get HTML for a warning box with an icon.
 657       *
 658       * @param string $text Wikitext, get this with wfMessage()->plain()
 659       *
 660       * @return string
 661       */
 662  	public function getWarningBox( $text ) {
 663          return $this->getInfoBox( $text, 'warning-32.png', 'config-warning-box' );
 664      }
 665  
 666      /**
 667       * Get HTML for an info box with an icon.
 668       *
 669       * @param string $text Wikitext, get this with wfMessage()->plain()
 670       * @param string|bool $icon Icon name, file in mw-config/images. Default: false
 671       * @param string|bool $class Additional class name to add to the wrapper div. Default: false.
 672       *
 673       * @return string
 674       */
 675  	public function getInfoBox( $text, $icon = false, $class = false ) {
 676          $text = $this->parse( $text, true );
 677          $icon = ( $icon == false ) ?
 678              'images/info-32.png' :
 679              'images/' . $icon;
 680          $alt = wfMessage( 'config-information' )->text();
 681  
 682          return Html::infoBox( $text, $icon, $alt, $class );
 683      }
 684  
 685      /**
 686       * Get small text indented help for a preceding form field.
 687       * Parameters like wfMessage().
 688       *
 689       * @param string $msg
 690       * @return string
 691       */
 692  	public function getHelpBox( $msg /*, ... */ ) {
 693          $args = func_get_args();
 694          array_shift( $args );
 695          $args = array_map( 'htmlspecialchars', $args );
 696          $text = wfMessage( $msg, $args )->useDatabase( false )->plain();
 697          $html = $this->parse( $text, true );
 698  
 699          return "<div class=\"mw-help-field-container\">\n" .
 700              "<span class=\"mw-help-field-hint\" title=\"" .
 701              wfMessage( 'config-help-tooltip' )->escaped() . "\">" .
 702              wfMessage( 'config-help' )->escaped() . "</span>\n" .
 703              "<span class=\"mw-help-field-data\">" . $html . "</span>\n" .
 704              "</div>\n";
 705      }
 706  
 707      /**
 708       * Output a help box.
 709       * @param string $msg Key for wfMessage()
 710       */
 711  	public function showHelpBox( $msg /*, ... */ ) {
 712          $args = func_get_args();
 713          $html = call_user_func_array( array( $this, 'getHelpBox' ), $args );
 714          $this->output->addHTML( $html );
 715      }
 716  
 717      /**
 718       * Show a short informational message.
 719       * Output looks like a list.
 720       *
 721       * @param string $msg
 722       */
 723  	public function showMessage( $msg /*, ... */ ) {
 724          $args = func_get_args();
 725          array_shift( $args );
 726          $html = '<div class="config-message">' .
 727              $this->parse( wfMessage( $msg, $args )->useDatabase( false )->plain() ) .
 728              "</div>\n";
 729          $this->output->addHTML( $html );
 730      }
 731  
 732      /**
 733       * @param Status $status
 734       */
 735  	public function showStatusMessage( Status $status ) {
 736          $errors = array_merge( $status->getErrorsArray(), $status->getWarningsArray() );
 737          foreach ( $errors as $error ) {
 738              call_user_func_array( array( $this, 'showMessage' ), $error );
 739          }
 740      }
 741  
 742      /**
 743       * Label a control by wrapping a config-input div around it and putting a
 744       * label before it.
 745       *
 746       * @param string $msg
 747       * @param string $forId
 748       * @param string $contents
 749       * @param string $helpData
 750       * @return string
 751       */
 752  	public function label( $msg, $forId, $contents, $helpData = "" ) {
 753          if ( strval( $msg ) == '' ) {
 754              $labelText = '&#160;';
 755          } else {
 756              $labelText = wfMessage( $msg )->escaped();
 757          }
 758  
 759          $attributes = array( 'class' => 'config-label' );
 760  
 761          if ( $forId ) {
 762              $attributes['for'] = $forId;
 763          }
 764  
 765          return "<div class=\"config-block\">\n" .
 766              "  <div class=\"config-block-label\">\n" .
 767              Xml::tags( 'label',
 768                  $attributes,
 769                  $labelText
 770              ) . "\n" .
 771              $helpData .
 772              "  </div>\n" .
 773              "  <div class=\"config-block-elements\">\n" .
 774              $contents .
 775              "  </div>\n" .
 776              "</div>\n";
 777      }
 778  
 779      /**
 780       * Get a labelled text box to configure a variable.
 781       *
 782       * @param mixed[] $params
 783       *    Parameters are:
 784       *      var:         The variable to be configured (required)
 785       *      label:       The message name for the label (required)
 786       *      attribs:     Additional attributes for the input element (optional)
 787       *      controlName: The name for the input element (optional)
 788       *      value:       The current value of the variable (optional)
 789       *      help:        The html for the help text (optional)
 790       *
 791       * @return string
 792       */
 793  	public function getTextBox( $params ) {
 794          if ( !isset( $params['controlName'] ) ) {
 795              $params['controlName'] = 'config_' . $params['var'];
 796          }
 797  
 798          if ( !isset( $params['value'] ) ) {
 799              $params['value'] = $this->getVar( $params['var'] );
 800          }
 801  
 802          if ( !isset( $params['attribs'] ) ) {
 803              $params['attribs'] = array();
 804          }
 805          if ( !isset( $params['help'] ) ) {
 806              $params['help'] = "";
 807          }
 808  
 809          return $this->label(
 810              $params['label'],
 811              $params['controlName'],
 812              Xml::input(
 813                  $params['controlName'],
 814                  30, // intended to be overridden by CSS
 815                  $params['value'],
 816                  $params['attribs'] + array(
 817                      'id' => $params['controlName'],
 818                      'class' => 'config-input-text',
 819                      'tabindex' => $this->nextTabIndex()
 820                  )
 821              ),
 822              $params['help']
 823          );
 824      }
 825  
 826      /**
 827       * Get a labelled textarea to configure a variable
 828       *
 829       * @param mixed[] $params
 830       *    Parameters are:
 831       *      var:         The variable to be configured (required)
 832       *      label:       The message name for the label (required)
 833       *      attribs:     Additional attributes for the input element (optional)
 834       *      controlName: The name for the input element (optional)
 835       *      value:       The current value of the variable (optional)
 836       *      help:        The html for the help text (optional)
 837       *
 838       * @return string
 839       */
 840  	public function getTextArea( $params ) {
 841          if ( !isset( $params['controlName'] ) ) {
 842              $params['controlName'] = 'config_' . $params['var'];
 843          }
 844  
 845          if ( !isset( $params['value'] ) ) {
 846              $params['value'] = $this->getVar( $params['var'] );
 847          }
 848  
 849          if ( !isset( $params['attribs'] ) ) {
 850              $params['attribs'] = array();
 851          }
 852          if ( !isset( $params['help'] ) ) {
 853              $params['help'] = "";
 854          }
 855  
 856          return $this->label(
 857              $params['label'],
 858              $params['controlName'],
 859              Xml::textarea(
 860                  $params['controlName'],
 861                  $params['value'],
 862                  30,
 863                  5,
 864                  $params['attribs'] + array(
 865                      'id' => $params['controlName'],
 866                      'class' => 'config-input-text',
 867                      'tabindex' => $this->nextTabIndex()
 868                  )
 869              ),
 870              $params['help']
 871          );
 872      }
 873  
 874      /**
 875       * Get a labelled password box to configure a variable.
 876       *
 877       * Implements password hiding
 878       * @param mixed[] $params
 879       *    Parameters are:
 880       *      var:         The variable to be configured (required)
 881       *      label:       The message name for the label (required)
 882       *      attribs:     Additional attributes for the input element (optional)
 883       *      controlName: The name for the input element (optional)
 884       *      value:       The current value of the variable (optional)
 885       *      help:        The html for the help text (optional)
 886       *
 887       * @return string
 888       */
 889  	public function getPasswordBox( $params ) {
 890          if ( !isset( $params['value'] ) ) {
 891              $params['value'] = $this->getVar( $params['var'] );
 892          }
 893  
 894          if ( !isset( $params['attribs'] ) ) {
 895              $params['attribs'] = array();
 896          }
 897  
 898          $params['value'] = $this->getFakePassword( $params['value'] );
 899          $params['attribs']['type'] = 'password';
 900  
 901          return $this->getTextBox( $params );
 902      }
 903  
 904      /**
 905       * Get a labelled checkbox to configure a boolean variable.
 906       *
 907       * @param mixed[] $params
 908       *    Parameters are:
 909       *      var:         The variable to be configured (required)
 910       *      label:       The message name for the label (required)
 911       *      attribs:     Additional attributes for the input element (optional)
 912       *      controlName: The name for the input element (optional)
 913       *      value:       The current value of the variable (optional)
 914       *      help:        The html for the help text (optional)
 915       *
 916       * @return string
 917       */
 918  	public function getCheckBox( $params ) {
 919          if ( !isset( $params['controlName'] ) ) {
 920              $params['controlName'] = 'config_' . $params['var'];
 921          }
 922  
 923          if ( !isset( $params['value'] ) ) {
 924              $params['value'] = $this->getVar( $params['var'] );
 925          }
 926  
 927          if ( !isset( $params['attribs'] ) ) {
 928              $params['attribs'] = array();
 929          }
 930          if ( !isset( $params['help'] ) ) {
 931              $params['help'] = "";
 932          }
 933          if ( isset( $params['rawtext'] ) ) {
 934              $labelText = $params['rawtext'];
 935          } else {
 936              $labelText = $this->parse( wfMessage( $params['label'] )->text() );
 937          }
 938  
 939          return "<div class=\"config-input-check\">\n" .
 940              $params['help'] .
 941              "<label>\n" .
 942              Xml::check(
 943                  $params['controlName'],
 944                  $params['value'],
 945                  $params['attribs'] + array(
 946                      'id' => $params['controlName'],
 947                      'tabindex' => $this->nextTabIndex(),
 948                  )
 949              ) .
 950              $labelText . "\n" .
 951              "</label>\n" .
 952              "</div>\n";
 953      }
 954  
 955      /**
 956       * Get a set of labelled radio buttons.
 957       *
 958       * @param mixed[] $params
 959       *    Parameters are:
 960       *      var:             The variable to be configured (required)
 961       *      label:           The message name for the label (required)
 962       *      itemLabelPrefix: The message name prefix for the item labels (required)
 963       *      itemLabels:      List of message names to use for the item labels instead of itemLabelPrefix, keyed by values
 964       *      values:          List of allowed values (required)
 965       *      itemAttribs:     Array of attribute arrays, outer key is the value name (optional)
 966       *      commonAttribs:   Attribute array applied to all items
 967       *      controlName:     The name for the input element (optional)
 968       *      value:           The current value of the variable (optional)
 969       *      help:            The html for the help text (optional)
 970       *
 971       * @return string
 972       */
 973  	public function getRadioSet( $params ) {
 974          $items = $this->getRadioElements( $params );
 975  
 976          if ( !isset( $params['label'] ) ) {
 977              $label = '';
 978          } else {
 979              $label = $params['label'];
 980          }
 981  
 982          if ( !isset( $params['controlName'] ) ) {
 983              $params['controlName'] = 'config_' . $params['var'];
 984          }
 985  
 986          if ( !isset( $params['help'] ) ) {
 987              $params['help'] = "";
 988          }
 989  
 990          $s = "<ul>\n";
 991          foreach ( $items as $value => $item ) {
 992              $s .= "<li>$item</li>\n";
 993          }
 994          $s .= "</ul>\n";
 995  
 996          return $this->label( $label, $params['controlName'], $s, $params['help'] );
 997      }
 998  
 999      /**
1000       * Get a set of labelled radio buttons. You probably want to use getRadioSet(), not this.
1001       *
1002       * @see getRadioSet
1003       *
1004       * @return array
1005       */
1006  	public function getRadioElements( $params ) {
1007          if ( !isset( $params['controlName'] ) ) {
1008              $params['controlName'] = 'config_' . $params['var'];
1009          }
1010  
1011          if ( !isset( $params['value'] ) ) {
1012              $params['value'] = $this->getVar( $params['var'] );
1013          }
1014  
1015          $items = array();
1016  
1017          foreach ( $params['values'] as $value ) {
1018              $itemAttribs = array();
1019  
1020              if ( isset( $params['commonAttribs'] ) ) {
1021                  $itemAttribs = $params['commonAttribs'];
1022              }
1023  
1024              if ( isset( $params['itemAttribs'][$value] ) ) {
1025                  $itemAttribs = $params['itemAttribs'][$value] + $itemAttribs;
1026              }
1027  
1028              $checked = $value == $params['value'];
1029              $id = $params['controlName'] . '_' . $value;
1030              $itemAttribs['id'] = $id;
1031              $itemAttribs['tabindex'] = $this->nextTabIndex();
1032  
1033              $items[$value] =
1034                  Xml::radio( $params['controlName'], $value, $checked, $itemAttribs ) .
1035                  '&#160;' .
1036                  Xml::tags( 'label', array( 'for' => $id ), $this->parse(
1037                      isset( $params['itemLabels'] ) ?
1038                          wfMessage( $params['itemLabels'][$value] )->plain() :
1039                          wfMessage( $params['itemLabelPrefix'] . strtolower( $value ) )->plain()
1040                  ) );
1041          }
1042  
1043          return $items;
1044      }
1045  
1046      /**
1047       * Output an error or warning box using a Status object.
1048       *
1049       * @param Status $status
1050       */
1051  	public function showStatusBox( $status ) {
1052          if ( !$status->isGood() ) {
1053              $text = $status->getWikiText();
1054  
1055              if ( $status->isOk() ) {
1056                  $box = $this->getWarningBox( $text );
1057              } else {
1058                  $box = $this->getErrorBox( $text );
1059              }
1060  
1061              $this->output->addHTML( $box );
1062          }
1063      }
1064  
1065      /**
1066       * Convenience function to set variables based on form data.
1067       * Assumes that variables containing "password" in the name are (potentially
1068       * fake) passwords.
1069       *
1070       * @param string[] $varNames
1071       * @param string $prefix The prefix added to variables to obtain form names
1072       *
1073       * @return string[]
1074       */
1075  	public function setVarsFromRequest( $varNames, $prefix = 'config_' ) {
1076          $newValues = array();
1077  
1078          foreach ( $varNames as $name ) {
1079              $value = $this->request->getVal( $prefix . $name );
1080              // bug 30524, do not trim passwords
1081              if ( stripos( $name, 'password' ) === false ) {
1082                  $value = trim( $value );
1083              }
1084              $newValues[$name] = $value;
1085  
1086              if ( $value === null ) {
1087                  // Checkbox?
1088                  $this->setVar( $name, false );
1089              } else {
1090                  if ( stripos( $name, 'password' ) !== false ) {
1091                      $this->setPassword( $name, $value );
1092                  } else {
1093                      $this->setVar( $name, $value );
1094                  }
1095              }
1096          }
1097  
1098          return $newValues;
1099      }
1100  
1101      /**
1102       * Helper for Installer::docLink()
1103       *
1104       * @param string $page
1105       *
1106       * @return string
1107       */
1108  	protected function getDocUrl( $page ) {
1109          $url = "{$_SERVER['PHP_SELF']}?page=" . urlencode( $page );
1110  
1111          if ( in_array( $this->currentPageName, $this->pageSequence ) ) {
1112              $url .= '&lastPage=' . urlencode( $this->currentPageName );
1113          }
1114  
1115          return $url;
1116      }
1117  
1118      /**
1119       * Extension tag hook for a documentation link.
1120       *
1121       * @param string $linkText
1122       * @param string[] $attribs
1123       * @param Parser $parser Unused
1124       *
1125       * @return string
1126       */
1127  	public function docLink( $linkText, $attribs, $parser ) {
1128          $url = $this->getDocUrl( $attribs['href'] );
1129  
1130          return '<a href="' . htmlspecialchars( $url ) . '">' .
1131              htmlspecialchars( $linkText ) .
1132              '</a>';
1133      }
1134  
1135      /**
1136       * Helper for "Download LocalSettings" link on WebInstall_Complete
1137       *
1138       * @param string $text Unused
1139       * @param string[] $attribs Unused
1140       * @param Parser $parser Unused
1141       *
1142       * @return string Html for download link
1143       */
1144  	public function downloadLinkHook( $text, $attribs, $parser ) {
1145          $anchor = Html::rawElement( 'a',
1146              array( 'href' => $this->getURL( array( 'localsettings' => 1 ) ) ),
1147              wfMessage( 'config-download-localsettings' )->parse()
1148          );
1149  
1150          return Html::rawElement( 'div', array( 'class' => 'config-download-link' ), $anchor );
1151      }
1152  
1153      /**
1154       * @return bool
1155       */
1156  	public function envCheckPath() {
1157          // PHP_SELF isn't available sometimes, such as when PHP is CGI but
1158          // cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME
1159          // to get the path to the current script... hopefully it's reliable. SIGH
1160          $path = false;
1161          if ( !empty( $_SERVER['PHP_SELF'] ) ) {
1162              $path = $_SERVER['PHP_SELF'];
1163          } elseif ( !empty( $_SERVER['SCRIPT_NAME'] ) ) {
1164              $path = $_SERVER['SCRIPT_NAME'];
1165          }
1166          if ( $path !== false ) {
1167              $scriptPath = preg_replace( '{^(.*)/(mw-)?config.*$}', '$1', $path );
1168              $scriptExtension = $this->getVar( 'wgScriptExtension' );
1169  
1170              $this->setVar( 'wgScriptPath', "$scriptPath" );
1171              // Update variables set from Setup.php that are derived from wgScriptPath
1172              $this->setVar( 'wgScript', "$scriptPath/index$scriptExtension" );
1173              $this->setVar( 'wgLoadScript', "$scriptPath/load$scriptExtension" );
1174              $this->setVar( 'wgStylePath', "$scriptPath/skins" );
1175              $this->setVar( 'wgLocalStylePath', "$scriptPath/skins" );
1176              $this->setVar( 'wgExtensionAssetsPath', "$scriptPath/extensions" );
1177              $this->setVar( 'wgUploadPath', "$scriptPath/images" );
1178  
1179          } else {
1180              $this->showError( 'config-no-uri' );
1181  
1182              return false;
1183          }
1184  
1185          return parent::envCheckPath();
1186      }
1187  
1188      /**
1189       * @return string
1190       */
1191  	protected function envGetDefaultServer() {
1192          return WebRequest::detectServer();
1193      }
1194  
1195      /**
1196       * Output stylesheet for web installer pages
1197       */
1198  	public function outputCss() {
1199          $this->request->response()->header( 'Content-type: text/css' );
1200          echo $this->output->getCSS();
1201      }
1202  
1203      /**
1204       * @return string[]
1205       */
1206  	public function getPhpErrors() {
1207          return $this->phpErrors;
1208      }
1209  
1210  }


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