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" .
639 $params = array_map(
'htmlspecialchars', $params );
640 $text =
wfMessage( $msg, $params )->useDatabase(
false )->plain();
641 $html = $this->
parse( $text,
true );
643 return "<div class=\"config-help-field-container\">\n" .
644 "<a class=\"config-help-field-hint\" title=\"" .
645 wfMessage(
'config-help-tooltip' )->escaped() .
"\">ℹ️ " .
646 wfMessage(
'config-help' )->escaped() .
"</a>\n" .
647 "<div class=\"config-help-field-content config-help-field-content-hidden " .
648 "cdx-message cdx-message--block cdx-message--notice\" style=\"margin: 10px\">" .
649 "<div class=\"cdx-message__content\">" . $html .
"</div></div>\n" .
661 HtmlArmor::getHtml( $text ) :
662 $this->
parse( $text,
true );
663 return '<div class="cdx-message cdx-message--block cdx-message--notice">' .
664 '<span class="cdx-message__icon"></span><div class="cdx-message__content">' .
665 '<p><strong>' .
wfMessage(
'config-information' )->escaped() .
'</strong></p>' .
671 $html =
'<div class="cdx-message cdx-message--block cdx-message--success">' .
672 '<span class="cdx-message__icon"></span><div class="cdx-message__content">' .
673 $this->
parse(
wfMessage( $msg, $params )->useDatabase(
false )->plain() ) .
675 $this->output->addHTML( $html );
679 $html =
'<div class="cdx-message cdx-message--block cdx-message--notice">' .
680 '<span class="cdx-message__icon"></span><div class="cdx-message__content">' .
681 $this->
parse(
wfMessage( $msg, $params )->useDatabase(
false )->plain() ) .
683 $this->output->addHTML( $html );
687 $html =
'<div class="cdx-message cdx-message--block cdx-message--warning">' .
688 '<span class="cdx-message__icon"></span><div class="cdx-message__content">' .
689 $this->
parse(
wfMessage( $msg, $params )->useDatabase(
false )->plain() ) .
691 $this->output->addHTML( $html );
696 foreach ( $status->
getMessages(
'error' ) as $msg ) {
699 foreach ( $status->
getMessages(
'warning' ) as $msg ) {
715 public function label( $msg, $forId, $contents, $helpData =
"" ) {
716 if ( strval( $msg ) ==
'' ) {
717 $labelText =
"\u{00A0}";
719 $labelText =
wfMessage( $msg )->escaped();
722 $attributes = [
'class' =>
'config-label' ];
725 $attributes[
'for'] = $forId;
728 return "<div class=\"config-block\">\n" .
729 " <div class=\"config-block-label\">\n" .
736 " <div class=\"config-block-elements\">\n" .
758 if ( !isset( $params[
'controlName'] ) ) {
759 $params[
'controlName'] =
'config_' . $params[
'var'];
762 if ( !isset( $params[
'value'] ) ) {
763 $params[
'value'] = $this->
getVar( $params[
'var'] );
766 if ( !isset( $params[
'attribs'] ) ) {
767 $params[
'attribs'] = [];
769 if ( !isset( $params[
'help'] ) ) {
770 $params[
'help'] =
"";
775 $params[
'controlName'],
776 "<div class=\"cdx-text-input\">" .
778 $params[
'controlName'],
781 $params[
'attribs'] + [
782 'id' => $params[
'controlName'],
783 'class' =>
'cdx-text-input__input',
806 if ( !isset( $params[
'controlName'] ) ) {
807 $params[
'controlName'] =
'config_' . $params[
'var'];
810 if ( !isset( $params[
'value'] ) ) {
811 $params[
'value'] = $this->
getVar( $params[
'var'] );
814 if ( !isset( $params[
'attribs'] ) ) {
815 $params[
'attribs'] = [];
817 if ( !isset( $params[
'help'] ) ) {
818 $params[
'help'] =
"";
823 $params[
'controlName'],
825 $params[
'controlName'],
829 $params[
'attribs'] + [
830 'id' => $params[
'controlName'],
831 'class' =>
'config-input-text',
856 if ( !isset( $params[
'value'] ) ) {
857 $params[
'value'] = $this->
getVar( $params[
'var'] );
860 if ( !isset( $params[
'attribs'] ) ) {
861 $params[
'attribs'] = [];
865 $params[
'attribs'][
'type'] =
'password';
877 private static function addClassAttrib( &$attribs, $class ) {
878 if ( isset( $attribs[
'class'] ) ) {
879 $attribs[
'class'] .=
' ' . $class;
881 $attribs[
'class'] = $class;
902 if ( !isset( $params[
'controlName'] ) ) {
903 $params[
'controlName'] =
'config_' . $params[
'var'];
906 if ( !isset( $params[
'value'] ) ) {
907 $params[
'value'] = $this->
getVar( $params[
'var'] );
910 if ( !isset( $params[
'attribs'] ) ) {
911 $params[
'attribs'] = [];
913 if ( !isset( $params[
'help'] ) ) {
914 $params[
'help'] =
"";
916 if ( !isset( $params[
'labelAttribs'] ) ) {
917 $params[
'labelAttribs'] = [];
919 $labelText = $params[
'rawtext'] ?? $this->
parse(
wfMessage( $params[
'label'] )->plain() );
920 $labelText =
'<span class="cdx-label__label__text"> ' . $labelText .
'</span>';
921 self::addClassAttrib( $params[
'attribs'],
'cdx-checkbox__input' );
922 self::addClassAttrib( $params[
'labelAttribs'],
'cdx-label__label' );
924 return "<div class=\"cdx-checkbox\" style=\"margin-top: 12px; margin-bottom: 2px;\">" .
925 "<div class=\"cdx-checkbox__wrapper\">\n" .
927 $params[
'controlName'],
929 $params[
'attribs'] + [
930 'id' => $params[
'controlName'],
934 "<span class=\"cdx-checkbox__icon\"></span>" .
935 "<div class=\"cdx-checkbox__label cdx-label\">" .
938 $params[
'labelAttribs'] + [
939 'for' => $params[
'controlName']
943 "</div></div></div>\n" . $params[
'help'];
969 $label = $params[
'label'] ??
'';
971 if ( !isset( $params[
'controlName'] ) ) {
972 $params[
'controlName'] =
'config_' . $params[
'var'];
975 if ( !isset( $params[
'help'] ) ) {
976 $params[
'help'] =
"";
980 foreach ( $items as $item ) {
984 return $this->
label( $label, $params[
'controlName'], $s, $params[
'help'] );
997 if ( !isset( $params[
'controlName'] ) ) {
998 $params[
'controlName'] =
'config_' . $params[
'var'];
1001 if ( !isset( $params[
'value'] ) ) {
1002 $params[
'value'] = $this->
getVar( $params[
'var'] );
1007 foreach ( $params[
'values'] as $value ) {
1010 if ( isset( $params[
'commonAttribs'] ) ) {
1011 $itemAttribs = $params[
'commonAttribs'];
1014 if ( isset( $params[
'itemAttribs'][$value] ) ) {
1015 $itemAttribs = $params[
'itemAttribs'][$value] + $itemAttribs;
1018 $checked = $value == $params[
'value'];
1019 $id = $params[
'controlName'] .
'_' . $value;
1020 $itemAttribs[
'id'] = $id;
1022 self::addClassAttrib( $itemAttribs,
'cdx-radio__input' );
1024 $radioText = $this->
parse(
1025 isset( $params[
'itemLabels'] ) ?
1026 wfMessage( $params[
'itemLabels'][$value] )->plain() :
1027 wfMessage( $params[
'itemLabelPrefix'] . strtolower( $value ) )->plain()
1030 '<span class="cdx-radio">' .
1031 '<span class="cdx-radio__wrapper">' .
1032 Xml::radio( $params[
'controlName'], $value, $checked, $itemAttribs ) .
1033 '<span class="cdx-radio__icon"></span>' .
1034 '<span class="cdx-radio__label cdx-label">' .
1037 [
'for' => $id,
'class' =>
'cdx-label__label' ],
1038 '<span class="cdx-label__label__text">' . $radioText .
'</span>'
1039 ) .
'</span></span></span>';
1051 if ( !$status->isGood() ) {
1052 $html = $status->getHTML();
1054 if ( $status->isOK() ) {
1055 $box = Html::warningBox( $html,
'config-warning-box' );
1057 $box = Html::errorBox( $html,
'',
'config-error-box' );
1060 $this->output->addHTML( $box );
1077 foreach ( $varNames as $name ) {
1078 $value = $this->request->getVal( $prefix . $name );
1080 if ( $value !==
null && stripos( $name,
'password' ) ===
false ) {
1081 $value = trim( $value );
1083 $newValues[$name] = $value;
1085 if ( $value ===
null ) {
1087 $this->
setVar( $name,
false );
1088 } elseif ( stripos( $name,
'password' ) !==
false ) {
1091 $this->
setVar( $name, $value );
1106 $query = [
'page' => $page ];
1108 if ( in_array( $this->currentPageName, $this->pageSequence ) ) {
1112 return $this->
getUrl( $query );
1124 return Html::rawElement(
'li', [],
1151 if ( !empty( $_SERVER[
'PHP_SELF'] ) ) {
1152 $path = $_SERVER[
'PHP_SELF'];
1153 } elseif ( !empty( $_SERVER[
'SCRIPT_NAME'] ) ) {
1154 $path = $_SERVER[
'SCRIPT_NAME'];
1156 if (
$path ===
false ) {
1161 return parent::envCheckPath();
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 );
1178 'wgScriptPath' =>
"$scriptPath",
1180 'wgScript' =>
"$scriptPath/index.php",
1181 'wgLoadScript' =>
"$scriptPath/load.php",
1182 'wgStylePath' =>
"$scriptPath/skins",
1183 'wgLocalStylePath' =>
"$scriptPath/skins",
1184 'wgExtensionAssetsPath' =>
"$scriptPath/extensions",
1185 'wgUploadPath' =>
"$scriptPath/images",
1186 'wgResourceBasePath' =>
"$scriptPath",
1196 $assumeProxiesUseDefaultProtocolPorts =
1197 $this->
getVar(
'wgAssumeProxiesUseDefaultProtocolPorts' );
1199 return WebRequest::detectServer( $assumeProxiesUseDefaultProtocolPorts );
1212 private function outputLS() {
1213 $this->request->response()->header(
'Content-type: application/x-httpd-php' );
1214 $this->request->response()->header(
1215 'Content-Disposition: attachment; filename="LocalSettings.php"'
1219 $rightsProfile = $this->rightsProfiles[$this->
getVar(
'_RightsProfile' )];
1220 foreach ( $rightsProfile as $group => $rightsArr ) {
1221 $ls->setGroupRights( $group, $rightsArr );
1223 echo $ls->getText();
1230 $this->request->response()->header(
'Content-type: text/css' );
1231 echo $this->output->getCSS();
1258 $dbInstaller->preUpgrade();
1262 $taskFactory->registerWebUpgradeTasks( $taskList );
1263 $taskRunner =
new TaskRunner( $taskList, $taskFactory, TaskFactory::PROFILE_WEB_UPGRADE );
1265 ob_start( [ $this,
'outputHandler' ] );
1267 $status = $taskRunner->execute();
1268 $ret = $status->isOK();
1270 $this->
setVar(
'_UpgradeDone',
true );
1271 }
catch ( Exception $e ) {
1273 echo
"\nAn error occurred:\n";
1274 echo $e->getMessage();
1283 return htmlspecialchars( $string );
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
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.