[ Index ] |
PHP Cross Reference of MediaWiki-1.24.0 |
[Summary view] [Print] [Text view]
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 = ' '; 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 ' ' . 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 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 14:03:12 2014 | Cross-referenced by PHPXref 0.7.1 |