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->getCheck(
'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( $this->request->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 ( $status->
getMessages(
'error' ) as $msg ) {
693 foreach ( $status->
getMessages(
'warning' ) as $msg ) {
709 public function label( $msg, $forId, $contents, $helpData =
"" ) {
710 if ( strval( $msg ) ==
'' ) {
711 $labelText =
"\u{00A0}";
713 $labelText =
wfMessage( $msg )->escaped();
716 $attributes = [
'class' =>
'config-label' ];
719 $attributes[
'for'] = $forId;
722 return "<div class=\"config-block\">\n" .
723 " <div class=\"config-block-label\">\n" .
730 " <div class=\"config-block-elements\">\n" .
752 if ( !isset(
$params[
'controlName'] ) ) {
756 if ( !isset(
$params[
'value'] ) ) {
760 if ( !isset(
$params[
'attribs'] ) ) {
763 if ( !isset(
$params[
'help'] ) ) {
770 "<div class=\"cdx-text-input\">" .
776 'id' =>
$params[
'controlName'],
777 'class' =>
'cdx-text-input__input',
800 if ( !isset(
$params[
'controlName'] ) ) {
804 if ( !isset(
$params[
'value'] ) ) {
808 if ( !isset(
$params[
'attribs'] ) ) {
811 if ( !isset(
$params[
'help'] ) ) {
824 'id' =>
$params[
'controlName'],
825 'class' =>
'config-input-text',
850 if ( !isset(
$params[
'value'] ) ) {
854 if ( !isset(
$params[
'attribs'] ) ) {
859 $params[
'attribs'][
'type'] =
'password';
871 private static function addClassAttrib( &$attribs, $class ) {
872 if ( isset( $attribs[
'class'] ) ) {
873 $attribs[
'class'] .=
' ' . $class;
875 $attribs[
'class'] = $class;
896 if ( !isset(
$params[
'controlName'] ) ) {
900 if ( !isset(
$params[
'value'] ) ) {
904 if ( !isset(
$params[
'attribs'] ) ) {
907 if ( !isset(
$params[
'help'] ) ) {
910 if ( !isset(
$params[
'labelAttribs'] ) ) {
914 self::addClassAttrib(
$params[
'attribs'],
'cdx-checkbox__input' );
915 self::addClassAttrib(
$params[
'labelAttribs'],
'cdx-checkbox__label' );
917 return "<div class=\"cdx-checkbox\" style=\"margin-top: 12px; margin-bottom: 2px;\">\n" .
922 'id' =>
$params[
'controlName'],
926 "<span class=\"cdx-checkbox__icon\"></span>" .
930 'for' =>
$params[
'controlName']
960 $label =
$params[
'label'] ??
'';
962 if ( !isset(
$params[
'controlName'] ) ) {
966 if ( !isset(
$params[
'help'] ) ) {
971 foreach ( $items as $item ) {
988 if ( !isset(
$params[
'controlName'] ) ) {
992 if ( !isset(
$params[
'value'] ) ) {
998 foreach (
$params[
'values'] as $value ) {
1001 if ( isset(
$params[
'commonAttribs'] ) ) {
1002 $itemAttribs =
$params[
'commonAttribs'];
1005 if ( isset(
$params[
'itemAttribs'][$value] ) ) {
1006 $itemAttribs =
$params[
'itemAttribs'][$value] + $itemAttribs;
1009 $checked = $value ==
$params[
'value'];
1010 $id =
$params[
'controlName'] .
'_' . $value;
1011 $itemAttribs[
'id'] = $id;
1013 self::addClassAttrib( $itemAttribs,
'cdx-radio__input' );
1016 '<span class="cdx-radio">' .
1018 "<span class=\"cdx-radio__icon\"></span>\u{00A0}" .
1019 Xml::tags(
'label', [
'for' => $id,
'class' =>
'cdx-radio__label' ], $this->
parse(
1020 isset(
$params[
'itemLabels'] ) ?
1035 if ( !$status->isGood() ) {
1036 $html = $status->getHTML();
1038 if ( $status->isOK() ) {
1039 $box = Html::warningBox( $html,
'config-warning-box' );
1041 $box = Html::errorBox( $html,
'',
'config-error-box' );
1044 $this->output->addHTML( $box );
1061 foreach ( $varNames as $name ) {
1062 $value = $this->request->getVal( $prefix . $name );
1064 if ( $value !==
null && stripos( $name,
'password' ) ===
false ) {
1065 $value = trim( $value );
1067 $newValues[$name] = $value;
1069 if ( $value ===
null ) {
1071 $this->
setVar( $name,
false );
1072 } elseif ( stripos( $name,
'password' ) !==
false ) {
1075 $this->
setVar( $name, $value );
1090 $query = [
'page' => $page ];
1092 if ( in_array( $this->currentPageName, $this->pageSequence ) ) {
1096 return $this->
getUrl( $query );
1108 return Html::rawElement(
'li', [],
1120 $anchor = Html::rawElement(
'a',
1121 [
'href' => $this->
getUrl( [
'localsettings' => 1 ] ) ],
1125 return Html::rawElement(
'div', [
'class' =>
'config-download-link' ], $anchor );
1150 if ( !empty( $_SERVER[
'PHP_SELF'] ) ) {
1151 $path = $_SERVER[
'PHP_SELF'];
1152 } elseif ( !empty( $_SERVER[
'SCRIPT_NAME'] ) ) {
1153 $path = $_SERVER[
'SCRIPT_NAME'];
1155 if (
$path ===
false ) {
1160 return parent::envCheckPath();
1164 parent::envPrepPath();
1169 if ( !empty( $_SERVER[
'PHP_SELF'] ) ) {
1170 $path = $_SERVER[
'PHP_SELF'];
1171 } elseif ( !empty( $_SERVER[
'SCRIPT_NAME'] ) ) {
1172 $path = $_SERVER[
'SCRIPT_NAME'];
1174 if (
$path !==
false ) {
1175 $scriptPath = preg_replace(
'{^(.*)/(mw-)?config.*$}',
'$1',
$path );
1177 $this->
setVar(
'wgScriptPath',
"$scriptPath" );
1179 $this->
setVar(
'wgScript',
"$scriptPath/index.php" );
1180 $this->
setVar(
'wgLoadScript',
"$scriptPath/load.php" );
1181 $this->
setVar(
'wgStylePath',
"$scriptPath/skins" );
1182 $this->
setVar(
'wgLocalStylePath',
"$scriptPath/skins" );
1183 $this->
setVar(
'wgExtensionAssetsPath',
"$scriptPath/extensions" );
1184 $this->
setVar(
'wgUploadPath',
"$scriptPath/images" );
1185 $this->
setVar(
'wgResourceBasePath',
"$scriptPath" );
1193 $assumeProxiesUseDefaultProtocolPorts =
1194 $this->
getVar(
'wgAssumeProxiesUseDefaultProtocolPorts' );
1196 return WebRequest::detectServer( $assumeProxiesUseDefaultProtocolPorts );
1202 private function outputLS() {
1203 $this->request->response()->header(
'Content-type: application/x-httpd-php' );
1204 $this->request->response()->header(
1205 'Content-Disposition: attachment; filename="LocalSettings.php"'
1209 $rightsProfile = $this->rightsProfiles[$this->
getVar(
'_RightsProfile' )];
1210 foreach ( $rightsProfile as $group => $rightsArr ) {
1211 $ls->setGroupRights( $group, $rightsArr );
1213 echo $ls->getText();
1220 $this->request->response()->header(
'Content-type: text/css' );
1221 echo $this->output->getCSS();
1241 protected static function infoBox( $rawHtml, $icon, $alt, $class =
'' ) {
1242 $s = Html::openElement(
'div', [
'class' =>
'mw-installer-box-left' ] ) .
1249 Html::closeElement(
'div' ) .
1250 Html::openElement(
'div', [
'class' =>
'mw-installer-box-right' ] ) .
1252 Html::closeElement(
'div' ) .
1255 return Html::warningBox( $s, $class )
1256 .
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.
getMessages(?string $type=null)
Returns a list of error messages, optionally only those of the given type.
$wgLanguageCode
Config variable stub for the LanguageCode setting, for use by phpdoc and IDEs.