X-Git-Url: https://scripts.mit.edu/gitweb/autoinstalls/mediawiki.git/blobdiff_plain/d57edfddd6c01f0ed6b1a84019649cdf6cddd5f8..83d871ca0d985c6d586b323bf96161afb510ebf6:/includes/installer/WebInstaller.php diff --git a/includes/installer/WebInstaller.php b/includes/installer/WebInstaller.php index 7d300132..639339d1 100644 --- a/includes/installer/WebInstaller.php +++ b/includes/installer/WebInstaller.php @@ -2,6 +2,21 @@ /** * Core installer web interface. * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * http://www.gnu.org/copyleft/gpl.html + * * @file * @ingroup Deployment */ @@ -29,25 +44,28 @@ class WebInstaller extends Installer { /** * Cached session array. * - * @var array + * @var array[] */ protected $session; /** * Captured PHP error text. Temporary. - * @var array + * + * @var string[] */ protected $phpErrors; /** * The main sequence of page names. These will be displayed in turn. - * To add one: - * * Add it here - * * Add a config-page- message - * * Add a WebInstaller_ class - * @var array + * + * To add a new installer page: + * * Add it to this WebInstaller::$pageSequence property + * * Add a "config-page-" message + * * Add a "WebInstaller" class + * + * @var string[] */ - public $pageSequence = array( + public $pageSequence = [ 'Language', 'ExistingWiki', 'Welcome', @@ -58,24 +76,26 @@ class WebInstaller extends Installer { 'Options', 'Install', 'Complete', - ); + ]; /** * Out of sequence pages, selectable by the user at any time. - * @var array + * + * @var string[] */ - protected $otherPages = array( + protected $otherPages = [ 'Restart', 'Readme', 'ReleaseNotes', 'Copying', 'UpgradeDoc', // Can't use Upgrade due to Upgrade step - ); + ]; /** * Array of pages which have declared that they have been submitted, have validated * their input, and need no further processing. - * @var array + * + * @var bool[] */ protected $happyPages; @@ -83,32 +103,34 @@ class WebInstaller extends Installer { * List of "skipped" pages. These are pages that will automatically continue * to the next page on any GET request. To avoid breaking the "back" button, * they need to be skipped during a back operation. - * @var array + * + * @var bool[] */ protected $skippedPages; /** * Flag indicating that session data may have been lost. + * * @var bool */ public $showSessionWarning = false; /** * Numeric index of the page we're on + * * @var int */ protected $tabIndex = 1; /** * Name of the page we're on + * * @var string */ protected $currentPageName; /** - * Constructor. - * - * @param $request WebRequest + * @param WebRequest $request */ public function __construct( WebRequest $request ) { parent::__construct(); @@ -117,16 +139,16 @@ class WebInstaller extends Installer { // Add parser hooks global $wgParser; - $wgParser->setHook( 'downloadlink', array( $this, 'downloadLinkHook' ) ); - $wgParser->setHook( 'doclink', array( $this, 'docLink' ) ); + $wgParser->setHook( 'downloadlink', [ $this, 'downloadLinkHook' ] ); + $wgParser->setHook( 'doclink', [ $this, 'docLink' ] ); } /** * Main entry point. * - * @param $session Array: initial session array + * @param array[] $session Initial session array * - * @return Array: new session array + * @return array[] New session array */ public function execute( array $session ) { $this->session = $session; @@ -135,44 +157,42 @@ class WebInstaller extends Installer { $this->settings = $session['settings'] + $this->settings; } - $this->exportVars(); $this->setupLanguage(); - if( ( $this->getVar( '_InstallDone' ) || $this->getVar( '_UpgradeDone' ) ) - && $this->request->getVal( 'localsettings' ) ) - { + if ( ( $this->getVar( '_InstallDone' ) || $this->getVar( '_UpgradeDone' ) ) + && $this->request->getVal( 'localsettings' ) + ) { $this->request->response()->header( 'Content-type: application/x-httpd-php' ); $this->request->response()->header( 'Content-Disposition: attachment; filename="LocalSettings.php"' ); - $ls = new LocalSettingsGenerator( $this ); + $ls = InstallerOverrides::getLocalSettingsGenerator( $this ); $rightsProfile = $this->rightsProfiles[$this->getVar( '_RightsProfile' )]; - foreach( $rightsProfile as $group => $rightsArr ) { + foreach ( $rightsProfile as $group => $rightsArr ) { $ls->setGroupRights( $group, $rightsArr ); } echo $ls->getText(); + return $this->session; } - $cssDir = $this->request->getVal( 'css' ); - if( $cssDir ) { - $cssDir = ( $cssDir == 'rtl' ? 'rtl' : 'ltr' ); - $this->request->response()->header( 'Content-type: text/css' ); - echo $this->output->getCSS( $cssDir ); + $isCSS = $this->request->getVal( 'css' ); + if ( $isCSS ) { + $this->outputCss(); return $this->session; } if ( isset( $session['happyPages'] ) ) { $this->happyPages = $session['happyPages']; } else { - $this->happyPages = array(); + $this->happyPages = []; } if ( isset( $session['skippedPages'] ) ) { $this->skippedPages = $session['skippedPages']; } else { - $this->skippedPages = array(); + $this->skippedPages = []; } $lowestUnhappy = $this->getLowestUnhappy(); @@ -183,6 +203,7 @@ class WebInstaller extends Installer { $this->output->useShortHeader(); $this->output->allowFrames(); $page->submitCC(); + return $this->finish(); } @@ -191,6 +212,7 @@ class WebInstaller extends Installer { $this->output->useShortHeader(); $this->output->allowFrames(); $this->output->addHTML( $page->getCCDoneBox() ); + return $this->finish(); } @@ -234,12 +256,13 @@ class WebInstaller extends Installer { do { $nextPageId--; $nextPage = $this->pageSequence[$nextPageId]; - } while( isset( $this->skippedPages[$nextPage] ) ); + } while ( isset( $this->skippedPages[$nextPage] ) ); } else { $nextPage = $this->pageSequence[$lowestUnhappy]; } - $this->output->redirect( $this->getUrl( array( 'page' => $nextPage ) ) ); + $this->output->redirect( $this->getUrl( [ 'page' => $nextPage ] ) ); + return $this->finish(); } @@ -247,6 +270,10 @@ class WebInstaller extends Installer { $this->currentPageName = $page->getName(); $this->startPageWrapper( $pageName ); + if ( $page->isSlow() ) { + $this->disableTimeLimit(); + } + $result = $page->execute(); $this->endPageWrapper(); @@ -280,7 +307,7 @@ class WebInstaller extends Installer { $nextPage = $this->pageSequence[$lowestUnhappy]; } - $this->output->redirect( $this->getUrl( array( 'page' => $nextPage ) ) ); + $this->output->redirect( $this->getUrl( [ 'page' => $nextPage ] ) ); } return $this->finish(); @@ -300,20 +327,28 @@ class WebInstaller extends Installer { /** * Start the PHP session. This may be called before execute() to start the PHP session. + * + * @throws Exception + * @return bool */ public function startSession() { - if( wfIniGetBool( 'session.auto_start' ) || session_id() ) { + if ( wfIniGetBool( 'session.auto_start' ) || session_id() ) { // Done already return true; } - $this->phpErrors = array(); - set_error_handler( array( $this, 'errorHandler' ) ); - session_start(); + $this->phpErrors = []; + set_error_handler( [ $this, 'errorHandler' ] ); + try { + session_name( 'mw_installer_session' ); + session_start(); + } catch ( Exception $e ) { + restore_error_handler(); + throw $e; + } restore_error_handler(); if ( $this->phpErrors ) { - $this->showError( 'config-session-error', $this->phpErrors[0] ); return false; } @@ -325,11 +360,13 @@ class WebInstaller extends Installer { * * This is used by mw-config/index.php to prevent multiple installations of MW * on the same cookie domain from interfering with each other. + * + * @return string */ public function getFingerprint() { // Get the base URL of the installation $url = $this->request->getFullRequestURL(); - if ( preg_match( '!^(.*\?)!', $url, $m) ) { + if ( preg_match( '!^(.*\?)!', $url, $m ) ) { // Trim query string $url = $m[1]; } @@ -338,26 +375,35 @@ class WebInstaller extends Installer { // the /mw-config/index.php. Kinda scary though? $url = $m[1]; } - return md5( serialize( array( - 'local path' => dirname( dirname( __FILE__ ) ), + + return md5( serialize( [ + 'local path' => dirname( __DIR__ ), 'url' => $url, 'version' => $GLOBALS['wgVersion'] - ) ) ); + ] ) ); } /** - * Show an error message in a box. Parameters are like wfMsg(). + * Show an error message in a box. Parameters are like wfMessage(), or + * alternatively, pass a Message object in. + * @param string|Message $msg */ public function showError( $msg /*...*/ ) { - $args = func_get_args(); - array_shift( $args ); - $args = array_map( 'htmlspecialchars', $args ); - $msg = wfMsgReal( $msg, $args, false, false, false ); - $this->output->addHTML( $this->getErrorBox( $msg ) ); + if ( !( $msg instanceof Message ) ) { + $args = func_get_args(); + array_shift( $args ); + $args = array_map( 'htmlspecialchars', $args ); + $msg = wfMessage( $msg, $args ); + } + $text = $msg->useDatabase( false )->plain(); + $this->output->addHTML( $this->getErrorBox( $text ) ); } /** * Temporary error handler for session start debugging. + * + * @param int $errno Unused + * @param string $errstr */ public function errorHandler( $errno, $errstr ) { $this->phpErrors[] = $errstr; @@ -366,7 +412,7 @@ class WebInstaller extends Installer { /** * Clean up from execute() * - * @return array + * @return array[] */ public function finish() { $this->output->output(); @@ -382,24 +428,25 @@ class WebInstaller extends Installer { * We're restarting the installation, reset the session, happyPages, etc */ public function reset() { - $this->session = array(); - $this->happyPages = array(); - $this->settings = array(); + $this->session = []; + $this->happyPages = []; + $this->settings = []; } /** * Get a URL for submission back to the same script. * - * @param $query: Array + * @param string[] $query + * * @return string */ - public function getUrl( $query = array() ) { + public function getUrl( $query = [] ) { $url = $this->request->getRequestURL(); # Remove existing query $url = preg_replace( '/\?.*$/', '', $url ); if ( $query ) { - $url .= '?' . wfArrayToCGI( $query ); + $url .= '?' . wfArrayToCgi( $query ); } return $url; @@ -408,14 +455,11 @@ class WebInstaller extends Installer { /** * Get a WebInstallerPage by name. * - * @param $pageName String + * @param string $pageName * @return WebInstallerPage */ public function getPageByName( $pageName ) { - // Totally lame way to force autoload of WebInstallerPage.php - class_exists( 'WebInstallerPage' ); - - $pageClass = 'WebInstaller_' . $pageName; + $pageClass = 'WebInstaller' . $pageName; return new $pageClass( $this ); } @@ -423,8 +467,10 @@ class WebInstaller extends Installer { /** * Get a session variable. * - * @param $name String - * @param $default + * @param string $name + * @param array $default + * + * @return array */ public function getSession( $name, $default = null ) { if ( !isset( $this->session[$name] ) ) { @@ -436,8 +482,9 @@ class WebInstaller extends Installer { /** * Set a session variable. - * @param $name String key for the variable - * @param $value Mixed + * + * @param string $name Key for the variable + * @param mixed $value */ public function setSession( $name, $value ) { $this->session[$name] = $value; @@ -445,6 +492,7 @@ class WebInstaller extends Installer { /** * Get the next tabindex attribute value. + * * @return int */ public function nextTabIndex() { @@ -460,11 +508,11 @@ class WebInstaller extends Installer { if ( $this->getSession( 'test' ) === null && !$this->request->wasPosted() ) { $wgLanguageCode = $this->getAcceptLanguage(); $wgLang = $wgContLang = Language::factory( $wgLanguageCode ); + RequestContext::getMain()->setLanguage( $wgLang ); $this->setVar( 'wgLanguageCode', $wgLanguageCode ); $this->setVar( '_UserLang', $wgLanguageCode ); } else { $wgLanguageCode = $this->getVar( 'wgLanguageCode' ); - $wgLang = Language::factory( $this->getVar( '_UserLang' ) ); $wgContLang = Language::factory( $wgLanguageCode ); } } @@ -477,7 +525,7 @@ class WebInstaller extends Installer { public function getAcceptLanguage() { global $wgLanguageCode, $wgRequest; - $mwLanguages = Language::getLanguageNames(); + $mwLanguages = Language::fetchLanguageNames(); $headerLanguages = array_keys( $wgRequest->getAcceptLang() ); foreach ( $headerLanguages as $lang ) { @@ -492,7 +540,7 @@ class WebInstaller extends Installer { /** * Called by execute() before page output starts, to show a page list. * - * @param $currentPageName String + * @param string $currentPageName */ private function startPageWrapper( $currentPageName ) { $s = "
\n"; @@ -515,9 +563,16 @@ class WebInstaller extends Installer { $s .= "
    \n"; $s .= $this->getPageListItem( 'Restart', true, $currentPageName ); - $s .= "
\n"; // end list pane - $s .= Html::element( 'h2', array(), - wfMsg( 'config-page-' . strtolower( $currentPageName ) ) ); + // End list pane + $s .= "\n"; + + // Messages: + // config-page-language, config-page-welcome, config-page-dbconnect, config-page-upgrade, + // config-page-dbsettings, config-page-name, config-page-options, config-page-install, + // config-page-complete, config-page-restart, config-page-readme, config-page-releasenotes, + // config-page-copying, config-page-upgradedoc, config-page-existingwiki + $s .= Html::element( 'h2', [], + wfMessage( 'config-page-' . strtolower( $currentPageName ) )->text() ); $this->output->addHTMLNoFlush( $s ); } @@ -525,18 +580,24 @@ class WebInstaller extends Installer { /** * Get a list item for the page list. * - * @param $pageName String - * @param $enabled Boolean - * @param $currentPageName String + * @param string $pageName + * @param bool $enabled + * @param string $currentPageName * * @return string */ private function getPageListItem( $pageName, $enabled, $currentPageName ) { $s = "
  • "; - $name = wfMsg( 'config-page-' . strtolower( $pageName ) ); + + // Messages: + // config-page-language, config-page-welcome, config-page-dbconnect, config-page-upgrade, + // config-page-dbsettings, config-page-name, config-page-options, config-page-install, + // config-page-complete, config-page-restart, config-page-readme, config-page-releasenotes, + // config-page-copying, config-page-upgradedoc, config-page-existingwiki + $name = wfMessage( 'config-page-' . strtolower( $pageName ) )->text(); if ( $enabled ) { - $query = array( 'page' => $pageName ); + $query = [ 'page' => $pageName ]; if ( !in_array( $pageName, $this->pageSequence ) ) { if ( in_array( $currentPageName, $this->pageSequence ) ) { @@ -544,9 +605,9 @@ class WebInstaller extends Installer { } $link = Html::element( 'a', - array( + [ 'href' => $this->getUrl( $query ) - ), + ], $name ); } else { @@ -560,9 +621,9 @@ class WebInstaller extends Installer { } } else { $s .= Html::element( 'span', - array( + [ 'class' => 'config-page-disabled' - ), + ], $name ); } @@ -577,16 +638,18 @@ class WebInstaller extends Installer { */ private function endPageWrapper() { $this->output->addHTMLNoFlush( - "
    \n" . - "\n" . - "
    \n" . + "
    \n" . + "\n" . + "
    \n" . "" ); } /** * Get HTML for an error box with an icon. * - * @param $text String: wikitext, get this with wfMsgNoTrans() + * @param string $text Wikitext, get this with wfMessage()->plain() + * + * @return string */ public function getErrorBox( $text ) { return $this->getInfoBox( $text, 'critical-32.png', 'config-error-box' ); @@ -595,7 +658,9 @@ class WebInstaller extends Installer { /** * Get HTML for a warning box with an icon. * - * @param $text String: wikitext, get this with wfMsgNoTrans() + * @param string $text Wikitext, get this with wfMessage()->plain() + * + * @return string */ public function getWarningBox( $text ) { return $this->getInfoBox( $text, 'warning-32.png', 'config-warning-box' ); @@ -604,54 +669,51 @@ class WebInstaller extends Installer { /** * Get HTML for an info box with an icon. * - * @param $text String: wikitext, get this with wfMsgNoTrans() - * @param $icon String: icon name, file in skins/common/images - * @param $class String: additional class name to add to the wrapper div + * @param string $text Wikitext, get this with wfMessage()->plain() + * @param string|bool $icon Icon name, file in mw-config/images. Default: false + * @param string|bool $class Additional class name to add to the wrapper div. Default: false. + * + * @return string */ - public function getInfoBox( $text, $icon = 'info-32.png', $class = false ) { - $s = - "
    \n" . - "
    \n" . - Html::element( 'img', - array( - 'src' => '../skins/common/images/' . $icon, - 'alt' => wfMsg( 'config-information' ), - ) - ) . "\n" . - "
    \n" . - "
    \n" . - $this->parse( $text, true ) . "\n" . - "
    \n" . - "
    \n" . - "
    \n"; - return $s; + public function getInfoBox( $text, $icon = false, $class = false ) { + $text = $this->parse( $text, true ); + $icon = ( $icon == false ) ? + 'images/info-32.png' : + 'images/' . $icon; + $alt = wfMessage( 'config-information' )->text(); + + return Html::infoBox( $text, $icon, $alt, $class ); } /** * Get small text indented help for a preceding form field. - * Parameters like wfMsg(). + * Parameters like wfMessage(). + * + * @param string $msg + * @return string */ public function getHelpBox( $msg /*, ... */ ) { $args = func_get_args(); array_shift( $args ); $args = array_map( 'htmlspecialchars', $args ); - $text = wfMsgReal( $msg, $args, false, false, false ); - $html = htmlspecialchars( $text ); + $text = wfMessage( $msg, $args )->useDatabase( false )->plain(); $html = $this->parse( $text, true ); - return "
    \n" . - "" . wfMsgHtml( 'config-help' ) . "\n" . - "" . $html . "\n" . - "
    \n"; + return "
    \n" . + "escaped() . "\">" . + wfMessage( 'config-help' )->escaped() . "\n" . + "
    " . $html . "
    \n" . + "
    \n"; } /** * Output a help box. - * @param $msg String key for wfMsg() + * @param string $msg Key for wfMessage() */ public function showHelpBox( $msg /*, ... */ ) { $args = func_get_args(); - $html = call_user_func_array( array( $this, 'getHelpBox' ), $args ); + $html = call_user_func_array( [ $this, 'getHelpBox' ], $args ); $this->output->addHTML( $html ); } @@ -659,56 +721,60 @@ class WebInstaller extends Installer { * Show a short informational message. * Output looks like a list. * - * @param $msg string + * @param string $msg */ public function showMessage( $msg /*, ... */ ) { $args = func_get_args(); array_shift( $args ); $html = '
    ' . - $this->parse( wfMsgReal( $msg, $args, false, false, false ) ) . + $this->parse( wfMessage( $msg, $args )->useDatabase( false )->plain() ) . "
    \n"; $this->output->addHTML( $html ); } /** - * @param $status Status + * @param Status $status */ public function showStatusMessage( Status $status ) { - $text = $status->getWikiText(); - $this->output->addWikiText( - "
    \n" . - $text . - "
    " - ); + $errors = array_merge( $status->getErrorsArray(), $status->getWarningsArray() ); + foreach ( $errors as $error ) { + call_user_func_array( [ $this, 'showMessage' ], $error ); + } } /** * Label a control by wrapping a config-input div around it and putting a * label before it. + * + * @param string $msg + * @param string $forId + * @param string $contents + * @param string $helpData + * @return string */ public function label( $msg, $forId, $contents, $helpData = "" ) { if ( strval( $msg ) == '' ) { $labelText = ' '; } else { - $labelText = wfMsgHtml( $msg ); + $labelText = wfMessage( $msg )->escaped(); } - $attributes = array( 'class' => 'config-label' ); + $attributes = [ 'class' => 'config-label' ]; if ( $forId ) { $attributes['for'] = $forId; } - return - "
    \n" . + return "
    \n" . "
    \n" . Xml::tags( 'label', $attributes, - $labelText ) . "\n" . - $helpData . + $labelText + ) . "\n" . + $helpData . "
    \n" . "
    \n" . - $contents . + $contents . "
    \n" . "
    \n"; } @@ -716,14 +782,16 @@ class WebInstaller extends Installer { /** * Get a labelled text box to configure a variable. * - * @param $params Array + * @param mixed[] $params * Parameters are: - * var: The variable to be configured (required) - * label: The message name for the label (required) - * attribs: Additional attributes for the input element (optional) + * var: The variable to be configured (required) + * label: The message name for the label (required) + * attribs: Additional attributes for the input element (optional) * controlName: The name for the input element (optional) - * value: The current value of the variable (optional) - * help: The html for the help text (optional) + * value: The current value of the variable (optional) + * help: The html for the help text (optional) + * + * @return string */ public function getTextBox( $params ) { if ( !isset( $params['controlName'] ) ) { @@ -735,40 +803,42 @@ class WebInstaller extends Installer { } if ( !isset( $params['attribs'] ) ) { - $params['attribs'] = array(); + $params['attribs'] = []; } if ( !isset( $params['help'] ) ) { $params['help'] = ""; } - return - $this->label( - $params['label'], + + return $this->label( + $params['label'], + $params['controlName'], + Xml::input( $params['controlName'], - Xml::input( - $params['controlName'], - 30, // intended to be overridden by CSS - $params['value'], - $params['attribs'] + array( - 'id' => $params['controlName'], - 'class' => 'config-input-text', - 'tabindex' => $this->nextTabIndex() - ) - ), - $params['help'] - ); + 30, // intended to be overridden by CSS + $params['value'], + $params['attribs'] + [ + 'id' => $params['controlName'], + 'class' => 'config-input-text', + 'tabindex' => $this->nextTabIndex() + ] + ), + $params['help'] + ); } /** * Get a labelled textarea to configure a variable * - * @param $params Array + * @param mixed[] $params * Parameters are: - * var: The variable to be configured (required) - * label: The message name for the label (required) - * attribs: Additional attributes for the input element (optional) + * var: The variable to be configured (required) + * label: The message name for the label (required) + * attribs: Additional attributes for the input element (optional) * controlName: The name for the input element (optional) - * value: The current value of the variable (optional) - * help: The html for the help text (optional) + * value: The current value of the variable (optional) + * help: The html for the help text (optional) + * + * @return string */ public function getTextArea( $params ) { if ( !isset( $params['controlName'] ) ) { @@ -780,42 +850,44 @@ class WebInstaller extends Installer { } if ( !isset( $params['attribs'] ) ) { - $params['attribs'] = array(); + $params['attribs'] = []; } if ( !isset( $params['help'] ) ) { $params['help'] = ""; } - return - $this->label( - $params['label'], + + return $this->label( + $params['label'], + $params['controlName'], + Xml::textarea( $params['controlName'], - Xml::textarea( - $params['controlName'], - $params['value'], - 30, - 5, - $params['attribs'] + array( - 'id' => $params['controlName'], - 'class' => 'config-input-text', - 'tabindex' => $this->nextTabIndex() - ) - ), - $params['help'] - ); + $params['value'], + 30, + 5, + $params['attribs'] + [ + 'id' => $params['controlName'], + 'class' => 'config-input-text', + 'tabindex' => $this->nextTabIndex() + ] + ), + $params['help'] + ); } /** * Get a labelled password box to configure a variable. * * Implements password hiding - * @param $params Array + * @param mixed[] $params * Parameters are: - * var: The variable to be configured (required) - * label: The message name for the label (required) - * attribs: Additional attributes for the input element (optional) + * var: The variable to be configured (required) + * label: The message name for the label (required) + * attribs: Additional attributes for the input element (optional) * controlName: The name for the input element (optional) - * value: The current value of the variable (optional) - * help: The html for the help text (optional) + * value: The current value of the variable (optional) + * help: The html for the help text (optional) + * + * @return string */ public function getPasswordBox( $params ) { if ( !isset( $params['value'] ) ) { @@ -823,7 +895,7 @@ class WebInstaller extends Installer { } if ( !isset( $params['attribs'] ) ) { - $params['attribs'] = array(); + $params['attribs'] = []; } $params['value'] = $this->getFakePassword( $params['value'] ); @@ -835,14 +907,16 @@ class WebInstaller extends Installer { /** * Get a labelled checkbox to configure a boolean variable. * - * @param $params Array + * @param mixed[] $params * Parameters are: - * var: The variable to be configured (required) - * label: The message name for the label (required) - * attribs: Additional attributes for the input element (optional) + * var: The variable to be configured (required) + * label: The message name for the label (required) + * attribs: Additional attributes for the input element (optional) * controlName: The name for the input element (optional) - * value: The current value of the variable (optional) - * help: The html for the help text (optional) + * value: The current value of the variable (optional) + * help: The html for the help text (optional) + * + * @return string */ public function getCheckBox( $params ) { if ( !isset( $params['controlName'] ) ) { @@ -854,28 +928,27 @@ class WebInstaller extends Installer { } if ( !isset( $params['attribs'] ) ) { - $params['attribs'] = array(); + $params['attribs'] = []; } if ( !isset( $params['help'] ) ) { $params['help'] = ""; } - if( isset( $params['rawtext'] ) ) { + if ( isset( $params['rawtext'] ) ) { $labelText = $params['rawtext']; } else { - $labelText = $this->parse( wfMsg( $params['label'] ) ); + $labelText = $this->parse( wfMessage( $params['label'] )->text() ); } - return - "
    \n" . + return "
    \n" . $params['help'] . "\n" . @@ -885,38 +958,69 @@ class WebInstaller extends Installer { /** * Get a set of labelled radio buttons. * - * @param $params Array + * @param mixed[] $params * Parameters are: - * var: The variable to be configured (required) - * label: The message name for the label (required) + * var: The variable to be configured (required) + * label: The message name for the label (required) * itemLabelPrefix: The message name prefix for the item labels (required) - * values: List of allowed values (required) - * itemAttribs Array of attribute arrays, outer key is the value name (optional) - * commonAttribs Attribute array applied to all items - * controlName: The name for the input element (optional) - * value: The current value of the variable (optional) - * help: The html for the help text (optional) + * itemLabels: List of message names to use for the item labels instead + * of itemLabelPrefix, keyed by values + * values: List of allowed values (required) + * itemAttribs: Array of attribute arrays, outer key is the value name (optional) + * commonAttribs: Attribute array applied to all items + * controlName: The name for the input element (optional) + * value: The current value of the variable (optional) + * help: The html for the help text (optional) + * + * @return string */ public function getRadioSet( $params ) { - if ( !isset( $params['controlName'] ) ) { - $params['controlName'] = 'config_' . $params['var']; - } - - if ( !isset( $params['value'] ) ) { - $params['value'] = $this->getVar( $params['var'] ); - } + $items = $this->getRadioElements( $params ); if ( !isset( $params['label'] ) ) { $label = ''; } else { $label = $params['label']; } + + if ( !isset( $params['controlName'] ) ) { + $params['controlName'] = 'config_' . $params['var']; + } + if ( !isset( $params['help'] ) ) { $params['help'] = ""; } + $s = "
      \n"; + foreach ( $items as $value => $item ) { + $s .= "
    • $item
    • \n"; + } + $s .= "
    \n"; + + return $this->label( $label, $params['controlName'], $s, $params['help'] ); + } + + /** + * Get a set of labelled radio buttons. You probably want to use getRadioSet(), not this. + * + * @see getRadioSet + * + * @param mixed[] $params + * @return array + */ + public function getRadioElements( $params ) { + if ( !isset( $params['controlName'] ) ) { + $params['controlName'] = 'config_' . $params['var']; + } + + if ( !isset( $params['value'] ) ) { + $params['value'] = $this->getVar( $params['var'] ); + } + + $items = []; + foreach ( $params['values'] as $value ) { - $itemAttribs = array(); + $itemAttribs = []; if ( isset( $params['commonAttribs'] ) ) { $itemAttribs = $params['commonAttribs']; @@ -931,29 +1035,29 @@ class WebInstaller extends Installer { $itemAttribs['id'] = $id; $itemAttribs['tabindex'] = $this->nextTabIndex(); - $s .= - '
  • ' . + $items[$value] = Xml::radio( $params['controlName'], $value, $checked, $itemAttribs ) . ' ' . - Xml::tags( 'label', array( 'for' => $id ), $this->parse( - wfMsgNoTrans( $params['itemLabelPrefix'] . strtolower( $value ) ) - ) ) . - "
  • \n"; + Xml::tags( 'label', [ 'for' => $id ], $this->parse( + isset( $params['itemLabels'] ) ? + wfMessage( $params['itemLabels'][$value] )->plain() : + wfMessage( $params['itemLabelPrefix'] . strtolower( $value ) )->plain() + ) ); } - $s .= "\n"; - - return $this->label( $label, $params['controlName'], $s, $params['help'] ); + return $items; } /** * Output an error or warning box using a Status object. + * + * @param Status $status */ public function showStatusBox( $status ) { - if( !$status->isGood() ) { + if ( !$status->isGood() ) { $text = $status->getWikiText(); - if( $status->isOk() ) { + if ( $status->isOK() ) { $box = $this->getWarningBox( $text ); } else { $box = $this->getErrorBox( $text ); @@ -968,14 +1072,20 @@ class WebInstaller extends Installer { * Assumes that variables containing "password" in the name are (potentially * fake) passwords. * - * @param $varNames Array - * @param $prefix String: the prefix added to variables to obtain form names + * @param string[] $varNames + * @param string $prefix The prefix added to variables to obtain form names + * + * @return string[] */ public function setVarsFromRequest( $varNames, $prefix = 'config_' ) { - $newValues = array(); + $newValues = []; foreach ( $varNames as $name ) { - $value = trim( $this->request->getVal( $prefix . $name ) ); + $value = $this->request->getVal( $prefix . $name ); + // T32524, do not trim passwords + if ( stripos( $name, 'password' ) === false ) { + $value = trim( $value ); + } $newValues[$name] = $value; if ( $value === null ) { @@ -1009,6 +1119,10 @@ class WebInstaller extends Installer { /** * Helper for Installer::docLink() + * + * @param string $page + * + * @return string */ protected function getDocUrl( $page ) { $url = "{$_SERVER['PHP_SELF']}?page=" . urlencode( $page ); @@ -1022,27 +1136,120 @@ class WebInstaller extends Installer { /** * Extension tag hook for a documentation link. + * + * @param string $linkText + * @param string[] $attribs + * @param Parser $parser Unused + * + * @return string */ public function docLink( $linkText, $attribs, $parser ) { $url = $this->getDocUrl( $attribs['href'] ); + return '' . htmlspecialchars( $linkText ) . ''; } - + /** * Helper for "Download LocalSettings" link on WebInstall_Complete - * @return String Html for download link + * + * @param string $text Unused + * @param string[] $attribs Unused + * @param Parser $parser Unused + * + * @return string Html for download link */ - public function downloadLinkHook( $text, $attribs, $parser ) { - $img = Html::element( 'img', array( - 'src' => '../skins/common/images/download-32.png', - 'width' => '32', - 'height' => '32', - ) ); + public function downloadLinkHook( $text, $attribs, $parser ) { $anchor = Html::rawElement( 'a', - array( 'href' => $this->getURL( array( 'localsettings' => 1 ) ) ), - $img . ' ' . wfMsgHtml( 'config-download-localsettings' ) ); - return Html::rawElement( 'div', array( 'class' => 'config-download-link' ), $anchor ); + [ 'href' => $this->getUrl( [ 'localsettings' => 1 ] ) ], + wfMessage( 'config-download-localsettings' )->parse() + ); + + return Html::rawElement( 'div', [ 'class' => 'config-download-link' ], $anchor ); + } + + /** + * If the software package wants the LocalSettings.php file + * to be placed in a specific location, override this function + * (see mw-config/overrides/README) to return the path of + * where the file should be saved, or false for a generic + * "in the base of your install" + * + * @since 1.27 + * @return string|bool + */ + public function getLocalSettingsLocation() { + return false; } + + /** + * @return bool + */ + public function envCheckPath() { + // PHP_SELF isn't available sometimes, such as when PHP is CGI but + // cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME + // to get the path to the current script... hopefully it's reliable. SIGH + $path = false; + if ( !empty( $_SERVER['PHP_SELF'] ) ) { + $path = $_SERVER['PHP_SELF']; + } elseif ( !empty( $_SERVER['SCRIPT_NAME'] ) ) { + $path = $_SERVER['SCRIPT_NAME']; + } + if ( $path === false ) { + $this->showError( 'config-no-uri' ); + return false; + } + + return parent::envCheckPath(); + } + + public function envPrepPath() { + parent::envPrepPath(); + // PHP_SELF isn't available sometimes, such as when PHP is CGI but + // cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME + // to get the path to the current script... hopefully it's reliable. SIGH + $path = false; + if ( !empty( $_SERVER['PHP_SELF'] ) ) { + $path = $_SERVER['PHP_SELF']; + } elseif ( !empty( $_SERVER['SCRIPT_NAME'] ) ) { + $path = $_SERVER['SCRIPT_NAME']; + } + if ( $path !== false ) { + $scriptPath = preg_replace( '{^(.*)/(mw-)?config.*$}', '$1', $path ); + + $this->setVar( 'wgScriptPath', "$scriptPath" ); + // Update variables set from Setup.php that are derived from wgScriptPath + $this->setVar( 'wgScript', "$scriptPath/index.php" ); + $this->setVar( 'wgLoadScript', "$scriptPath/load.php" ); + $this->setVar( 'wgStylePath', "$scriptPath/skins" ); + $this->setVar( 'wgLocalStylePath', "$scriptPath/skins" ); + $this->setVar( 'wgExtensionAssetsPath', "$scriptPath/extensions" ); + $this->setVar( 'wgUploadPath', "$scriptPath/images" ); + $this->setVar( 'wgResourceBasePath', "$scriptPath" ); + } + } + + /** + * @return string + */ + protected function envGetDefaultServer() { + return WebRequest::detectServer(); + } + + /** + * Output stylesheet for web installer pages + */ + public function outputCss() { + $this->request->response()->header( 'Content-type: text/css' ); + echo $this->output->getCSS(); + } + + /** + * @return string[] + */ + public function getPhpErrors() { + return $this->phpErrors; + } + }