155 parent::__construct();
170 if ( isset(
$session[
'settings'] ) ) {
173 foreach ( $this->settings as $key => $val ) {
174 $GLOBALS[$key] = $val;
180 if ( ( $this->
getVar(
'_InstallDone' ) || $this->
getVar(
'_UpgradeDone' ) )
181 && $this->request->getVal(
'localsettings' )
187 $isCSS = $this->request->getVal(
'css' );
193 $this->happyPages =
$session[
'happyPages'] ?? [];
195 $this->skippedPages =
$session[
'skippedPages'] ?? [];
200 $pageName = $this->request->getVal(
'page',
'' );
202 if ( in_array( $pageName, $this->otherPages ) ) {
208 if ( !$pageName || !in_array( $pageName, $this->pageSequence ) ) {
209 $pageId = $lowestUnhappy;
211 $pageId = array_search( $pageName, $this->pageSequence );
214 # If necessary, move back to the lowest-numbered unhappy page
215 if ( $pageId > $lowestUnhappy ) {
216 $pageId = $lowestUnhappy;
217 if ( $lowestUnhappy == 0 ) {
218 # Knocked back to start, possible loss of session data.
219 $this->showSessionWarning =
true;
223 $pageName = $this->pageSequence[$pageId];
227 # If a back button was submitted, go back without submitting the form data.
228 if ( $this->request->wasPosted() && $this->request->getBool(
'submit-back' ) ) {
229 if ( $this->request->getVal(
'lastPage' ) ) {
230 $nextPage = $this->request->getVal(
'lastPage' );
231 } elseif ( $pageId !==
false ) {
233 # Skip the skipped pages
234 $nextPageId = $pageId;
238 $nextPage = $this->pageSequence[$nextPageId];
239 }
while ( isset( $this->skippedPages[$nextPage] ) );
241 $nextPage = $this->pageSequence[$lowestUnhappy];
244 $this->output->redirect( $this->
getUrl( [
'page' => $nextPage ] ) );
250 $this->currentPageName = $page->getName();
251 $this->startPageWrapper( $pageName );
253 if ( $page->isSlow() ) {
257 $result = $page->execute();
259 $this->endPageWrapper();
261 if ( $result ==
'skip' ) {
262 # Page skipped without explicit submission.
263 # Skip it when we click "back" so that we don't just go forward again.
264 $this->skippedPages[$pageName] =
true;
265 $result =
'continue';
267 unset( $this->skippedPages[$pageName] );
270 # If it was posted, the page can request a continue to the next page.
271 if ( $result ===
'continue' && !$this->output->headerDone() ) {
272 if ( $pageId !==
false ) {
273 $this->happyPages[$pageId] =
true;
278 if ( $this->request->getVal(
'lastPage' ) ) {
279 $nextPage = $this->request->getVal(
'lastPage' );
280 } elseif ( $pageId !==
false ) {
281 $nextPage = $this->pageSequence[$pageId + 1];
283 $nextPage = $this->pageSequence[$lowestUnhappy];
286 if ( array_search( $nextPage, $this->pageSequence ) > $lowestUnhappy ) {
287 $nextPage = $this->pageSequence[$lowestUnhappy];
290 $this->output->redirect( $this->
getUrl( [
'page' => $nextPage ] ) );
301 if ( count( $this->happyPages ) == 0 ) {
304 return max( array_keys( $this->happyPages ) ) + 1;
315 if (
wfIniGetBool(
'session.auto_start' ) || session_id() ) {
322 if ( $this->request->getProtocol() ===
'https' ) {
323 $options[
'cookie_secure'] =
'1';
326 $this->phpErrors = [];
327 set_error_handler( [ $this,
'errorHandler' ] );
329 session_name(
'mw_installer_session' );
330 session_start( $options );
331 }
catch ( Exception $e ) {
332 restore_error_handler();
335 restore_error_handler();
337 if ( $this->phpErrors ) {
354 $url = $this->request->getFullRequestURL();
355 if ( preg_match(
'!^(.*\?)!', $url, $m ) ) {
359 if ( preg_match(
'!^(.*)/[^/]*/[^/]*$!', $url, $m ) ) {
365 return md5( serialize( [
366 'local path' => dirname( __DIR__ ),
373 if ( !( $msg instanceof
Message ) ) {
376 array_map(
'htmlspecialchars',
$params )
379 $text = $msg->useDatabase(
false )->parse();
380 $box = Html::errorBox( $text,
'',
'config-error-box' );
381 $this->output->addHTML( $box );
391 $this->phpErrors[] = $errstr;
400 $this->output->output();
414 $this->happyPages = [];
415 $this->settings = [];
426 $url = $this->request->getRequestURL();
427 # Remove existing query
428 $url = preg_replace(
'/\?.*$/',
'', $url );
444 $pageClass =
'MediaWiki\\Installer\\WebInstaller' . $pageName;
446 return new $pageClass( $this );
458 return $this->session[$name] ?? $default;
468 $this->session[$name] = $value;
477 return $this->tabIndex++;
486 if ( $this->
getSession(
'test' ) ===
null && !$this->request->wasPosted() ) {
490 RequestContext::getMain()->setLanguage(
$wgLang );
491 $this->
setVar(
'wgLanguageCode', $wgLanguageCode );
492 $this->
setVar(
'_UserLang', $wgLanguageCode );
508 ->getLanguageNameUtils()
509 ->getLanguageNames( LanguageNameUtils::AUTONYMS, LanguageNameUtils::SUPPORTED );
510 $headerLanguages = array_keys(
$wgRequest->getAcceptLang() );
512 foreach ( $headerLanguages as $lang ) {
513 if ( isset( $mwLanguages[$lang] ) ) {
527 $s =
"<div class=\"config-page-wrapper\">\n";
528 $s .=
"<div class=\"config-page\">\n";
529 $s .=
"<div class=\"config-page-list cdx-card\"><span class=\"cdx-card__text\">";
530 $s .=
"<span class=\"cdx-card__text__description\"><ul>\n";
533 foreach ( $this->pageSequence as $id => $pageName ) {
534 $happy = !empty( $this->happyPages[$id] );
535 $s .= $this->getPageListItem(
537 $happy || $lastHappy == $id - 1,
546 $s .=
"</ul><br/><ul>\n";
549 $s .=
"</ul></span></span></div>\n";
559 $this->output->addHTMLNoFlush( $s );
572 $s =
"<li class=\"config-page-list-item\">";
579 $name =
wfMessage(
'config-page-' . strtolower( $pageName ) )->text();
582 $query = [
'page' => $pageName ];
584 if ( !in_array( $pageName, $this->pageSequence ) ) {
591 'href' => $this->
getUrl( $query )
596 $link = htmlspecialchars( $name );
600 $s .=
"<span class=\"config-page-current\">$link</span>";
607 'class' =>
'config-page-disabled'
621 private function endPageWrapper() {
622 $this->output->addHTMLNoFlush(
623 "<div class=\"visualClear\"></div>\n" .
625 "<div class=\"visualClear\"></div>\n" .
637 public function getInfoBox( $text, $icon =
false, $class =
'' ) {
639 HtmlArmor::getHtml( $text ) :
640 $this->
parse( $text,
true );
641 $alt =
wfMessage(
'config-information' )->text();
656 $args = array_map(
'htmlspecialchars', $args );
657 $text =
wfMessage( $msg, $args )->useDatabase(
false )->plain();
658 $html = $this->
parse( $text,
true );
660 return "<div class=\"config-help-field-container\">\n" .
661 "<a class=\"config-help-field-hint\" title=\"" .
662 wfMessage(
'config-help-tooltip' )->escaped() .
"\">ℹ️ " .
663 wfMessage(
'config-help' )->escaped() .
"</a>\n" .
664 "<div class=\"config-help-field-content config-help-field-content-hidden " .
665 "cdx-message cdx-message--block cdx-message--notice\" style=\"margin: 10px\">" .
666 "<div class=\"cdx-message__content\">" . $html .
"</div></div>\n" .
677 $this->output->addHTML( $html );
681 $html =
'<div class="cdx-message cdx-message--block cdx-message--notice">' .
682 '<span class="cdx-message__icon"></span><div class="cdx-message__content">' .
685 $this->output->addHTML( $html );
690 foreach ( $errors as $error ) {
706 public function label( $msg, $forId, $contents, $helpData =
"" ) {
707 if ( strval( $msg ) ==
'' ) {
708 $labelText =
"\u{00A0}";
710 $labelText =
wfMessage( $msg )->escaped();
713 $attributes = [
'class' =>
'config-label' ];
716 $attributes[
'for'] = $forId;
719 return "<div class=\"config-block\">\n" .
720 " <div class=\"config-block-label\">\n" .
727 " <div class=\"config-block-elements\">\n" .
749 if ( !isset(
$params[
'controlName'] ) ) {
753 if ( !isset(
$params[
'value'] ) ) {
757 if ( !isset(
$params[
'attribs'] ) ) {
760 if ( !isset(
$params[
'help'] ) ) {
767 "<div class=\"cdx-text-input\">" .
773 'id' =>
$params[
'controlName'],
774 'class' =>
'cdx-text-input__input',
797 if ( !isset(
$params[
'controlName'] ) ) {
801 if ( !isset(
$params[
'value'] ) ) {
805 if ( !isset(
$params[
'attribs'] ) ) {
808 if ( !isset(
$params[
'help'] ) ) {
821 'id' =>
$params[
'controlName'],
822 'class' =>
'config-input-text',
847 if ( !isset(
$params[
'value'] ) ) {
851 if ( !isset(
$params[
'attribs'] ) ) {
856 $params[
'attribs'][
'type'] =
'password';
868 private static function addClassAttrib( &$attribs, $class ) {
869 if ( isset( $attribs[
'class'] ) ) {
870 $attribs[
'class'] .=
' ' . $class;
872 $attribs[
'class'] = $class;
893 if ( !isset(
$params[
'controlName'] ) ) {
897 if ( !isset(
$params[
'value'] ) ) {
901 if ( !isset(
$params[
'attribs'] ) ) {
904 if ( !isset(
$params[
'help'] ) ) {
907 if ( !isset(
$params[
'labelAttribs'] ) ) {
911 self::addClassAttrib(
$params[
'attribs'],
'cdx-checkbox__input' );
912 self::addClassAttrib(
$params[
'labelAttribs'],
'cdx-checkbox__label' );
914 return "<div class=\"cdx-checkbox\" style=\"margin-top: 12px; margin-bottom: 2px;\">\n" .
919 'id' =>
$params[
'controlName'],
923 "<span class=\"cdx-checkbox__icon\"></span>" .
927 'for' =>
$params[
'controlName']
957 $label =
$params[
'label'] ??
'';
959 if ( !isset(
$params[
'controlName'] ) ) {
963 if ( !isset(
$params[
'help'] ) ) {
968 foreach ( $items as $item ) {
985 if ( !isset(
$params[
'controlName'] ) ) {
989 if ( !isset(
$params[
'value'] ) ) {
995 foreach (
$params[
'values'] as $value ) {
998 if ( isset(
$params[
'commonAttribs'] ) ) {
999 $itemAttribs =
$params[
'commonAttribs'];
1002 if ( isset(
$params[
'itemAttribs'][$value] ) ) {
1003 $itemAttribs =
$params[
'itemAttribs'][$value] + $itemAttribs;
1006 $checked = $value ==
$params[
'value'];
1007 $id =
$params[
'controlName'] .
'_' . $value;
1008 $itemAttribs[
'id'] = $id;
1010 self::addClassAttrib( $itemAttribs,
'cdx-radio__input' );
1013 '<span class="cdx-radio">' .
1014 Xml::radio(
$params[
'controlName'], $value, $checked, $itemAttribs ) .
1015 "<span class=\"cdx-radio__icon\"></span>\u{00A0}" .
1016 Xml::tags(
'label', [
'for' => $id,
'class' =>
'cdx-radio__label' ], $this->
parse(
1017 isset(
$params[
'itemLabels'] ) ?
1032 if ( !$status->isGood() ) {
1033 $html = $status->getHTML();
1035 if ( $status->isOK() ) {
1036 $box = Html::warningBox( $html,
'config-warning-box' );
1038 $box = Html::errorBox( $html,
'',
'config-error-box' );
1041 $this->output->addHTML( $box );
1058 foreach ( $varNames as $name ) {
1059 $value = $this->request->getVal( $prefix . $name );
1061 if ( $value !==
null && stripos( $name,
'password' ) ===
false ) {
1062 $value = trim( $value );
1064 $newValues[$name] = $value;
1066 if ( $value ===
null ) {
1068 $this->
setVar( $name,
false );
1069 } elseif ( stripos( $name,
'password' ) !==
false ) {
1072 $this->
setVar( $name, $value );
1087 $query = [
'page' => $page ];
1089 if ( in_array( $this->currentPageName, $this->pageSequence ) ) {
1093 return $this->
getUrl( $query );
1105 return Html::rawElement(
'li', [],
1117 $anchor = Html::rawElement(
'a',
1118 [
'href' => $this->
getUrl( [
'localsettings' => 1 ] ) ],
1122 return Html::rawElement(
'div', [
'class' =>
'config-download-link' ], $anchor );
1147 if ( !empty( $_SERVER[
'PHP_SELF'] ) ) {
1148 $path = $_SERVER[
'PHP_SELF'];
1149 } elseif ( !empty( $_SERVER[
'SCRIPT_NAME'] ) ) {
1150 $path = $_SERVER[
'SCRIPT_NAME'];
1152 if (
$path ===
false ) {
1157 return parent::envCheckPath();
1161 parent::envPrepPath();
1166 if ( !empty( $_SERVER[
'PHP_SELF'] ) ) {
1167 $path = $_SERVER[
'PHP_SELF'];
1168 } elseif ( !empty( $_SERVER[
'SCRIPT_NAME'] ) ) {
1169 $path = $_SERVER[
'SCRIPT_NAME'];
1171 if (
$path !==
false ) {
1172 $scriptPath = preg_replace(
'{^(.*)/(mw-)?config.*$}',
'$1',
$path );
1174 $this->
setVar(
'wgScriptPath',
"$scriptPath" );
1176 $this->
setVar(
'wgScript',
"$scriptPath/index.php" );
1177 $this->
setVar(
'wgLoadScript',
"$scriptPath/load.php" );
1178 $this->
setVar(
'wgStylePath',
"$scriptPath/skins" );
1179 $this->
setVar(
'wgLocalStylePath',
"$scriptPath/skins" );
1180 $this->
setVar(
'wgExtensionAssetsPath',
"$scriptPath/extensions" );
1181 $this->
setVar(
'wgUploadPath',
"$scriptPath/images" );
1182 $this->
setVar(
'wgResourceBasePath',
"$scriptPath" );
1190 $assumeProxiesUseDefaultProtocolPorts =
1191 $this->
getVar(
'wgAssumeProxiesUseDefaultProtocolPorts' );
1193 return WebRequest::detectServer( $assumeProxiesUseDefaultProtocolPorts );
1199 private function outputLS() {
1200 $this->request->response()->header(
'Content-type: application/x-httpd-php' );
1201 $this->request->response()->header(
1202 'Content-Disposition: attachment; filename="LocalSettings.php"'
1206 $rightsProfile = $this->rightsProfiles[$this->
getVar(
'_RightsProfile' )];
1207 foreach ( $rightsProfile as $group => $rightsArr ) {
1208 $ls->setGroupRights( $group, $rightsArr );
1210 echo $ls->getText();
1217 $this->request->response()->header(
'Content-type: text/css' );
1218 echo $this->output->getCSS();
1238 protected static function infoBox( $rawHtml, $icon, $alt, $class =
'' ) {
1239 $s = Html::openElement(
'div', [
'class' =>
'mw-installer-box-left' ] ) .
1246 Html::closeElement(
'div' ) .
1247 Html::openElement(
'div', [
'class' =>
'mw-installer-box-right' ] ) .
1249 Html::closeElement(
'div' ) .
1252 return Html::warningBox( $s, $class )
1253 .
Html::element(
'div', [
'style' =>
'clear: left;' ],
' ' );
const MW_VERSION
The running version of MediaWiki.
wfIniGetBool( $setting)
Safety wrapper around ini_get() for boolean settings.
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
if(!defined( 'MW_NO_SESSION') &&MW_ENTRY_POINT !=='cli' $wgLang
array $params
The job parameters.
Marks HTML that shouldn't be escaped.
Group all the pieces relevant to the context of a request into one instance.
Module of static functions for generating XML.
$wgLanguageCode
Config variable stub for the LanguageCode setting, for use by phpdoc and IDEs.