MediaWiki master
WebInstaller.php
Go to the documentation of this file.
1<?php
24namespace MediaWiki\Installer;
25
26use Exception;
38
45class WebInstaller extends Installer {
46
50 public $output;
51
57 public $request;
58
64 protected $session;
65
71 protected $phpErrors;
72
83 public $pageSequence = [
84 'Language',
85 'ExistingWiki',
86 'Welcome',
87 'DBConnect',
88 'Upgrade',
89 'DBSettings',
90 'Name',
91 'Options',
92 'Install',
93 'Complete',
94 ];
95
101 protected $otherPages = [
102 'Restart',
103 'ReleaseNotes',
104 'Copying',
105 'UpgradeDoc', // Can't use Upgrade due to Upgrade step
106 ];
107
114 protected $happyPages;
115
123 protected $skippedPages;
124
130 public $showSessionWarning = false;
131
137 protected $tabIndex = 1;
138
144 protected $helpBoxId = 1;
145
152
153 public function __construct( WebRequest $request ) {
154 parent::__construct();
155 $this->output = new WebInstallerOutput( $this );
156 $this->request = $request;
157 }
158
166 public function execute( array $session ) {
167 $this->session = $session;
168
169 if ( isset( $session['settings'] ) ) {
170 $this->settings = $session['settings'] + $this->settings;
171 // T187586 MediaWikiServices works with globals
172 foreach ( $this->settings as $key => $val ) {
173 $GLOBALS[$key] = $val;
174 }
175 }
176
177 $this->setupLanguage();
178
179 if ( ( $this->getVar( '_InstallDone' ) || $this->getVar( '_UpgradeDone' ) )
180 && $this->request->getVal( 'localsettings' )
181 ) {
182 $this->outputLS();
183 return $this->session;
184 }
185
186 $isCSS = $this->request->getCheck( 'css' );
187 if ( $isCSS ) {
188 $this->outputCss();
189 return $this->session;
190 }
191
192 $this->happyPages = $session['happyPages'] ?? [];
193
194 $this->skippedPages = $session['skippedPages'] ?? [];
195
196 $lowestUnhappy = $this->getLowestUnhappy();
197
198 # Get the page name.
199 $pageName = $this->request->getVal( 'page', '' );
200
201 if ( in_array( $pageName, $this->otherPages ) ) {
202 # Out of sequence
203 $pageId = false;
204 $page = $this->getPageByName( $pageName );
205 } else {
206 # Main sequence
207 if ( !$pageName || !in_array( $pageName, $this->pageSequence ) ) {
208 $pageId = $lowestUnhappy;
209 } else {
210 $pageId = array_search( $pageName, $this->pageSequence );
211 }
212
213 # If necessary, move back to the lowest-numbered unhappy page
214 if ( $pageId > $lowestUnhappy ) {
215 $pageId = $lowestUnhappy;
216 if ( $lowestUnhappy == 0 ) {
217 # Knocked back to start, possible loss of session data.
218 $this->showSessionWarning = true;
219 }
220 }
221
222 $pageName = $this->pageSequence[$pageId];
223 $page = $this->getPageByName( $pageName );
224 }
225
226 # If a back button was submitted, go back without submitting the form data.
227 if ( $this->request->wasPosted() && $this->request->getBool( 'submit-back' ) ) {
228 if ( $this->request->getVal( 'lastPage' ) ) {
229 $nextPage = $this->request->getVal( 'lastPage' );
230 } elseif ( $pageId !== false ) {
231 # Main sequence page
232 # Skip the skipped pages
233 $nextPageId = $pageId;
234
235 do {
236 $nextPageId--;
237 $nextPage = $this->pageSequence[$nextPageId];
238 } while ( isset( $this->skippedPages[$nextPage] ) );
239 } else {
240 $nextPage = $this->pageSequence[$lowestUnhappy];
241 }
242
243 $this->output->redirect( $this->getUrl( [ 'page' => $nextPage ] ) );
244
245 return $this->finish();
246 }
247
248 # Execute the page.
249 $this->currentPageName = $page->getName();
250 $this->startPageWrapper( $pageName );
251
252 if ( $page->isSlow() ) {
253 $this->disableTimeLimit();
254 }
255
256 $result = $page->execute();
257
258 $this->endPageWrapper();
259
260 if ( $result == 'skip' ) {
261 # Page skipped without explicit submission.
262 # Skip it when we click "back" so that we don't just go forward again.
263 $this->skippedPages[$pageName] = true;
264 $result = 'continue';
265 } else {
266 unset( $this->skippedPages[$pageName] );
267 }
268
269 # If it was posted, the page can request a continue to the next page.
270 if ( $result === 'continue' && !$this->output->headerDone() ) {
271 if ( $pageId !== false ) {
272 $this->happyPages[$pageId] = true;
273 }
274
275 $lowestUnhappy = $this->getLowestUnhappy();
276
277 if ( $this->request->getVal( 'lastPage' ) ) {
278 $nextPage = $this->request->getVal( 'lastPage' );
279 } elseif ( $pageId !== false ) {
280 $nextPage = $this->pageSequence[$pageId + 1];
281 } else {
282 $nextPage = $this->pageSequence[$lowestUnhappy];
283 }
284
285 if ( array_search( $nextPage, $this->pageSequence ) > $lowestUnhappy ) {
286 $nextPage = $this->pageSequence[$lowestUnhappy];
287 }
288
289 $this->output->redirect( $this->getUrl( [ 'page' => $nextPage ] ) );
290 }
291
292 return $this->finish();
293 }
294
299 public function getLowestUnhappy() {
300 if ( count( $this->happyPages ) == 0 ) {
301 return 0;
302 } else {
303 return max( array_keys( $this->happyPages ) ) + 1;
304 }
305 }
306
313 public function startSession() {
314 if ( wfIniGetBool( 'session.auto_start' ) || session_id() ) {
315 // Done already
316 return true;
317 }
318
319 // Use secure cookies if we are on HTTPS
320 $options = [];
321 if ( $this->request->getProtocol() === 'https' ) {
322 $options['cookie_secure'] = '1';
323 }
324
325 $this->phpErrors = [];
326 set_error_handler( $this->errorHandler( ... ) );
327 try {
328 session_name( 'mw_installer_session' );
329 session_start( $options );
330 } catch ( Exception $e ) {
331 restore_error_handler();
332 throw $e;
333 }
334 restore_error_handler();
335
336 if ( $this->phpErrors ) {
337 return false;
338 }
339
340 return true;
341 }
342
351 public function getFingerprint() {
352 // Get the base URL of the installation
353 $url = $this->request->getFullRequestURL();
354 if ( preg_match( '!^(.*\?)!', $url, $m ) ) {
355 // Trim query string
356 $url = $m[1];
357 }
358 if ( preg_match( '!^(.*)/[^/]*/[^/]*$!', $url, $m ) ) {
359 // This... seems to try to get the base path from
360 // the /mw-config/index.php. Kinda scary though?
361 $url = $m[1];
362 }
363
364 return md5( serialize( [
365 'local path' => dirname( __DIR__ ),
366 'url' => $url,
367 'version' => MW_VERSION
368 ] ) );
369 }
370
371 public function showError( $msg, ...$params ) {
372 if ( !( $msg instanceof Message ) ) {
373 $msg = wfMessage(
374 $msg,
375 array_map( 'htmlspecialchars', $params )
376 );
377 }
378 $text = $msg->useDatabase( false )->parse();
379 $box = Html::errorBox( $text, '', 'config-error-box' );
380 $this->output->addHTML( $box );
381 }
382
389 public function errorHandler( $errno, $errstr ) {
390 $this->phpErrors[] = $errstr;
391 }
392
398 public function finish() {
399 $this->output->output();
400
401 $this->session['happyPages'] = $this->happyPages;
402 $this->session['skippedPages'] = $this->skippedPages;
403 $this->session['settings'] = $this->settings;
404
405 return $this->session;
406 }
407
411 public function reset() {
412 $this->session = [];
413 $this->happyPages = [];
414 $this->settings = [];
415 }
416
424 public function getUrl( $query = [] ) {
425 $url = $this->request->getRequestURL();
426 # Remove existing query
427 $url = preg_replace( '/\?.*$/', '', $url );
428
429 if ( $query ) {
430 $url .= '?' . wfArrayToCgi( $query );
431 }
432
433 return $url;
434 }
435
442 public function getPageByName( $pageName ) {
443 $pageClass = 'MediaWiki\\Installer\\WebInstaller' . $pageName;
444
445 return new $pageClass( $this );
446 }
447
456 public function getSession( $name, $default = null ) {
457 return $this->session[$name] ?? $default;
458 }
459
466 public function setSession( $name, $value ) {
467 $this->session[$name] = $value;
468 }
469
475 public function nextTabIndex() {
476 return $this->tabIndex++;
477 }
478
482 public function setupLanguage() {
483 global $wgLang, $wgLanguageCode;
484
485 if ( $this->getSession( 'test' ) === null && !$this->request->wasPosted() ) {
487 $wgLang = MediaWikiServices::getInstance()->getLanguageFactory()
488 ->getLanguage( $wgLanguageCode );
489 RequestContext::getMain()->setLanguage( $wgLang );
490 $this->setVar( 'wgLanguageCode', $wgLanguageCode );
491 $this->setVar( '_UserLang', $wgLanguageCode );
492 } else {
493 $wgLanguageCode = $this->getVar( 'wgLanguageCode' );
494 }
495 }
496
503 public function getAcceptLanguage() {
504 global $wgLanguageCode;
505
506 $mwLanguages = MediaWikiServices::getInstance()
507 ->getLanguageNameUtils()
508 ->getLanguageNames( LanguageNameUtils::AUTONYMS, LanguageNameUtils::SUPPORTED );
509 $headerLanguages = array_keys( $this->request->getAcceptLang() );
510
511 foreach ( $headerLanguages as $lang ) {
512 if ( isset( $mwLanguages[$lang] ) ) {
513 return $lang;
514 }
515 }
516
517 return $wgLanguageCode;
518 }
519
525 private function startPageWrapper( $currentPageName ) {
526 $s = "<div class=\"config-page-wrapper\">\n";
527 $s .= "<div class=\"config-page\">\n";
528 $s .= "<div class=\"config-page-list cdx-card\"><span class=\"cdx-card__text\">";
529 $s .= "<span class=\"cdx-card__text__description\"><ul>\n";
530 $lastHappy = -1;
531
532 foreach ( $this->pageSequence as $id => $pageName ) {
533 $happy = !empty( $this->happyPages[$id] );
534 $s .= $this->getPageListItem(
535 $pageName,
536 $happy || $lastHappy == $id - 1,
538 );
539
540 if ( $happy ) {
541 $lastHappy = $id;
542 }
543 }
544
545 $s .= "</ul><br/><ul>\n";
546 $s .= $this->getPageListItem( 'Restart', true, $currentPageName );
547 // End list pane
548 $s .= "</ul></span></span></div>\n";
549
550 // Messages:
551 // config-page-language, config-page-welcome, config-page-dbconnect, config-page-upgrade,
552 // config-page-dbsettings, config-page-name, config-page-options, config-page-install,
553 // config-page-complete, config-page-restart, config-page-releasenotes,
554 // config-page-copying, config-page-upgradedoc, config-page-existingwiki
555 $s .= Html::element( 'h2', [],
556 wfMessage( 'config-page-' . strtolower( $currentPageName ) )->text() );
557
558 $this->output->addHTMLNoFlush( $s );
559 }
560
570 private function getPageListItem( $pageName, $enabled, $currentPageName ) {
571 $s = "<li class=\"config-page-list-item\">";
572
573 // Messages:
574 // config-page-language, config-page-welcome, config-page-dbconnect, config-page-upgrade,
575 // config-page-dbsettings, config-page-name, config-page-options, config-page-install,
576 // config-page-complete, config-page-restart, config-page-releasenotes,
577 // config-page-copying, config-page-upgradedoc, config-page-existingwiki
578 $name = wfMessage( 'config-page-' . strtolower( $pageName ) )->text();
579
580 if ( $enabled ) {
581 $query = [ 'page' => $pageName ];
582
583 if ( !in_array( $pageName, $this->pageSequence ) ) {
584 if ( in_array( $currentPageName, $this->pageSequence ) ) {
585 $query['lastPage'] = $currentPageName;
586 }
587
588 $link = Html::element( 'a',
589 [
590 'href' => $this->getUrl( $query )
591 ],
592 $name
593 );
594 } else {
595 $link = htmlspecialchars( $name );
596 }
597
598 if ( $pageName == $currentPageName ) {
599 $s .= "<span class=\"config-page-current\">$link</span>";
600 } else {
601 $s .= $link;
602 }
603 } else {
604 $s .= Html::element( 'span',
605 [
606 'class' => 'config-page-disabled'
607 ],
608 $name
609 );
610 }
611
612 $s .= "</li>\n";
613
614 return $s;
615 }
616
620 private function endPageWrapper() {
621 $this->output->addHTMLNoFlush(
622 "<div class=\"visualClear\"></div>\n" .
623 "</div>\n" .
624 "<div class=\"visualClear\"></div>\n" .
625 "</div>" );
626 }
627
637 public function getHelpBox( $msg, ...$params ) {
638 $params = array_map( 'htmlspecialchars', $params );
639 $text = wfMessage( $msg, $params )->useDatabase( false )->plain();
640 $html = $this->parse( $text, true );
641
642 return "<div class=\"config-help-field-container\">\n" .
643 "<a class=\"config-help-field-hint\" title=\"" .
644 wfMessage( 'config-help-tooltip' )->escaped() . "\">ℹ️ " .
645 wfMessage( 'config-help' )->escaped() . "</a>\n" .
646 "<div class=\"config-help-field-content config-help-field-content-hidden " .
647 "cdx-message cdx-message--block cdx-message--notice\" style=\"margin: 10px\">" .
648 "<div class=\"cdx-message__content\">" . $html . "</div></div>\n" .
649 "</div>\n";
650 }
651
658 public function getInfoBox( $text ) {
659 $html = ( $text instanceof HtmlArmor ) ?
660 HtmlArmor::getHtml( $text ) :
661 $this->parse( $text, true );
662 return '<div class="cdx-message cdx-message--block cdx-message--notice">' .
663 '<span class="cdx-message__icon"></span><div class="cdx-message__content">' .
664 '<p><strong>' . wfMessage( 'config-information' )->escaped() . '</strong></p>' .
665 $html .
666 "</div></div>\n";
667 }
668
669 public function showSuccess( $msg, ...$params ) {
670 $html = '<div class="cdx-message cdx-message--block cdx-message--success">' .
671 '<span class="cdx-message__icon"></span><div class="cdx-message__content">' .
672 $this->parse( wfMessage( $msg, $params )->useDatabase( false )->plain() ) .
673 "</div></div>\n";
674 $this->output->addHTML( $html );
675 }
676
677 public function showMessage( $msg, ...$params ) {
678 $html = '<div class="cdx-message cdx-message--block cdx-message--notice">' .
679 '<span class="cdx-message__icon"></span><div class="cdx-message__content">' .
680 $this->parse( wfMessage( $msg, $params )->useDatabase( false )->plain() ) .
681 "</div></div>\n";
682 $this->output->addHTML( $html );
683 }
684
685 public function showWarning( $msg, ...$params ) {
686 $html = '<div class="cdx-message cdx-message--block cdx-message--warning">' .
687 '<span class="cdx-message__icon"></span><div class="cdx-message__content">' .
688 $this->parse( wfMessage( $msg, $params )->useDatabase( false )->plain() ) .
689 "</div></div>\n";
690 $this->output->addHTML( $html );
691 }
692
693 public function showStatusMessage( Status $status ) {
694 // Show errors at the top in web installer to make them easier to notice
695 foreach ( $status->getMessages( 'error' ) as $msg ) {
696 $this->showWarning( $msg );
697 }
698 foreach ( $status->getMessages( 'warning' ) as $msg ) {
699 $this->showWarning( $msg );
700 }
701 }
702
714 public function label( $msg, $forId, $contents, $helpData = "" ) {
715 if ( strval( $msg ) == '' ) {
716 $labelText = "\u{00A0}";
717 } else {
718 $labelText = wfMessage( $msg )->escaped();
719 }
720
721 $attributes = [ 'class' => 'config-label' ];
722
723 if ( $forId ) {
724 $attributes['for'] = $forId;
725 }
726
727 return "<div class=\"config-block\">\n" .
728 " <div class=\"config-block-label\">\n" .
729 Html::rawElement( 'label',
730 $attributes,
731 $labelText
732 ) . "\n" .
733 $helpData .
734 " </div>\n" .
735 " <div class=\"config-block-elements\">\n" .
736 $contents .
737 " </div>\n" .
738 "</div>\n";
739 }
740
756 public function getTextBox( $params ) {
757 if ( !isset( $params['controlName'] ) ) {
758 $params['controlName'] = 'config_' . $params['var'];
759 }
760
761 if ( !isset( $params['value'] ) ) {
762 $params['value'] = $this->getVar( $params['var'] );
763 }
764
765 if ( !isset( $params['attribs'] ) ) {
766 $params['attribs'] = [];
767 }
768 if ( !isset( $params['help'] ) ) {
769 $params['help'] = "";
770 }
771
772 return $this->label(
773 $params['label'],
774 $params['controlName'],
775 "<div class=\"cdx-text-input\">" .
776 Html::input(
777 $params['controlName'],
778 $params['value'],
779 'text',
780 $params['attribs'] + [
781 'id' => $params['controlName'],
782 'size' => 30, // intended to be overridden by CSS
783 'class' => 'cdx-text-input__input',
784 'tabindex' => $this->nextTabIndex()
785 ]
786 ) . "</div>",
787 $params['help']
788 );
789 }
790
805 public function getTextArea( $params ) {
806 if ( !isset( $params['controlName'] ) ) {
807 $params['controlName'] = 'config_' . $params['var'];
808 }
809
810 if ( !isset( $params['value'] ) ) {
811 $params['value'] = $this->getVar( $params['var'] );
812 }
813
814 if ( !isset( $params['attribs'] ) ) {
815 $params['attribs'] = [];
816 }
817 if ( !isset( $params['help'] ) ) {
818 $params['help'] = "";
819 }
820
821 return $this->label(
822 $params['label'],
823 $params['controlName'],
824 Html::textarea(
825 $params['controlName'],
826 $params['value'],
827 $params['attribs'] + [
828 'id' => $params['controlName'],
829 'cols' => 30,
830 'rows' => 5,
831 'class' => 'config-input-text',
832 'tabindex' => $this->nextTabIndex()
833 ]
834 ),
835 $params['help']
836 );
837 }
838
855 public function getPasswordBox( $params ) {
856 if ( !isset( $params['value'] ) ) {
857 $params['value'] = $this->getVar( $params['var'] );
858 }
859
860 if ( !isset( $params['attribs'] ) ) {
861 $params['attribs'] = [];
862 }
863
864 $params['value'] = $this->getFakePassword( $params['value'] );
865 $params['attribs']['type'] = 'password';
866
867 return $this->getTextBox( $params );
868 }
869
886 public function getCheckBox( $params ) {
887 if ( !isset( $params['controlName'] ) ) {
888 $params['controlName'] = 'config_' . $params['var'];
889 }
890
891 if ( !isset( $params['value'] ) ) {
892 $params['value'] = $this->getVar( $params['var'] );
893 }
894
895 if ( !isset( $params['attribs'] ) ) {
896 $params['attribs'] = [];
897 }
898 if ( !isset( $params['help'] ) ) {
899 $params['help'] = "";
900 }
901 if ( !isset( $params['labelAttribs'] ) ) {
902 $params['labelAttribs'] = [];
903 }
904 $labelText = $params['rawtext'] ?? $this->parse( wfMessage( $params['label'] )->plain() );
905 $labelText = '<span class="cdx-label__label__text"> ' . $labelText . '</span>';
906 Html::addClass( $params['attribs']['class'], 'cdx-checkbox__input' );
907 Html::addClass( $params['labelAttribs']['class'], 'cdx-label__label' );
908
909 return "<div class=\"cdx-checkbox\" style=\"margin-top: 12px; margin-bottom: 2px;\">" .
910 "<div class=\"cdx-checkbox__wrapper\">\n" .
911 Html::check(
912 $params['controlName'],
913 $params['value'],
914 $params['attribs'] + [
915 'id' => $params['controlName'],
916 'tabindex' => $this->nextTabIndex()
917 ]
918 ) .
919 "<span class=\"cdx-checkbox__icon\"></span>" .
920 "<div class=\"cdx-checkbox__label cdx-label\">" .
921 Html::rawElement(
922 'label',
923 $params['labelAttribs'] + [
924 'for' => $params['controlName']
925 ],
926 $labelText
927 ) .
928 "</div></div></div>\n" . $params['help'];
929 }
930
951 public function getRadioSet( $params ) {
952 $items = $this->getRadioElements( $params );
953
954 $label = $params['label'] ?? '';
955
956 if ( !isset( $params['controlName'] ) ) {
957 $params['controlName'] = 'config_' . $params['var'];
958 }
959
960 if ( !isset( $params['help'] ) ) {
961 $params['help'] = "";
962 }
963
964 $s = "";
965 foreach ( $items as $item ) {
966 $s .= "$item\n";
967 }
968
969 return $this->label( $label, $params['controlName'], $s, $params['help'] );
970 }
971
981 public function getRadioElements( $params ) {
982 if ( !isset( $params['controlName'] ) ) {
983 $params['controlName'] = 'config_' . $params['var'];
984 }
985
986 if ( !isset( $params['value'] ) ) {
987 $params['value'] = $this->getVar( $params['var'] );
988 }
989
990 $items = [];
991
992 foreach ( $params['values'] as $value ) {
993 $itemAttribs = [];
994
995 if ( isset( $params['commonAttribs'] ) ) {
996 $itemAttribs = $params['commonAttribs'];
997 }
998
999 if ( isset( $params['itemAttribs'][$value] ) ) {
1000 $itemAttribs = $params['itemAttribs'][$value] + $itemAttribs;
1001 }
1002
1003 $checked = $value == $params['value'];
1004 $id = $params['controlName'] . '_' . $value;
1005 $itemAttribs['id'] = $id;
1006 $itemAttribs['tabindex'] = $this->nextTabIndex();
1007 Html::addClass( $itemAttribs['class'], 'cdx-radio__input' );
1008
1009 $radioText = $this->parse(
1010 isset( $params['itemLabels'] ) ?
1011 wfMessage( $params['itemLabels'][$value] )->plain() :
1012 wfMessage( $params['itemLabelPrefix'] . strtolower( $value ) )->plain()
1013 );
1014 $items[$value] =
1015 '<span class="cdx-radio">' .
1016 '<span class="cdx-radio__wrapper">' .
1017 Html::radio( $params['controlName'], $checked, $itemAttribs + [ 'value' => $value ] ) .
1018 '<span class="cdx-radio__icon"></span>' .
1019 '<span class="cdx-radio__label cdx-label">' .
1020 Html::rawElement(
1021 'label',
1022 [ 'for' => $id, 'class' => 'cdx-label__label' ],
1023 '<span class="cdx-label__label__text">' . $radioText . '</span>'
1024 ) . '</span></span></span>';
1025 }
1026
1027 return $items;
1028 }
1029
1035 public function showStatusBox( $status ) {
1036 if ( !$status->isGood() ) {
1037 $html = $status->getHTML();
1038
1039 if ( $status->isOK() ) {
1040 $box = Html::warningBox( $html, 'config-warning-box' );
1041 } else {
1042 $box = Html::errorBox( $html, '', 'config-error-box' );
1043 }
1044
1045 $this->output->addHTML( $box );
1046 }
1047 }
1048
1059 public function setVarsFromRequest( $varNames, $prefix = 'config_' ) {
1060 $newValues = [];
1061
1062 foreach ( $varNames as $name ) {
1063 $value = $this->request->getVal( $prefix . $name );
1064 // T32524, do not trim passwords
1065 if ( $value !== null && stripos( $name, 'password' ) === false ) {
1066 $value = trim( $value );
1067 }
1068 $newValues[$name] = $value;
1069
1070 if ( $value === null ) {
1071 // Checkbox?
1072 $this->setVar( $name, false );
1073 } elseif ( stripos( $name, 'password' ) !== false ) {
1074 $this->setPassword( $name, $value );
1075 } else {
1076 $this->setVar( $name, $value );
1077 }
1078 }
1079
1080 return $newValues;
1081 }
1082
1090 public function getDocUrl( $page ) {
1091 $query = [ 'page' => $page ];
1092
1093 if ( in_array( $this->currentPageName, $this->pageSequence ) ) {
1094 $query['lastPage'] = $this->currentPageName;
1095 }
1096
1097 return $this->getUrl( $query );
1098 }
1099
1108 public function makeLinkItem( $url, $linkText ) {
1109 return Html::rawElement( 'li', [],
1110 Html::element( 'a', [ 'href' => $url ], $linkText )
1111 );
1112 }
1113
1124 public function getLocalSettingsLocation() {
1125 return false;
1126 }
1127
1131 public function envCheckPath() {
1132 // PHP_SELF isn't available sometimes, such as when PHP is CGI but
1133 // cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME
1134 // to get the path to the current script... hopefully it's reliable. SIGH
1135 $path = false;
1136 if ( !empty( $_SERVER['PHP_SELF'] ) ) {
1137 $path = $_SERVER['PHP_SELF'];
1138 } elseif ( !empty( $_SERVER['SCRIPT_NAME'] ) ) {
1139 $path = $_SERVER['SCRIPT_NAME'];
1140 }
1141 if ( $path === false ) {
1142 $this->showError( 'config-no-uri' );
1143 return false;
1144 }
1145
1146 return parent::envCheckPath();
1147 }
1148
1149 protected function detectWebPaths() {
1150 // PHP_SELF isn't available sometimes, such as when PHP is CGI but
1151 // cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME
1152 // to get the path to the current script... hopefully it's reliable. SIGH
1153 $path = false;
1154 if ( !empty( $_SERVER['PHP_SELF'] ) ) {
1155 $path = $_SERVER['PHP_SELF'];
1156 } elseif ( !empty( $_SERVER['SCRIPT_NAME'] ) ) {
1157 $path = $_SERVER['SCRIPT_NAME'];
1158 }
1159 if ( $path !== false ) {
1160 $scriptPath = preg_replace( '{^(.*)/(mw-)?config.*$}', '$1', $path );
1161
1162 return [
1163 'wgScriptPath' => "$scriptPath",
1164 // Update variables set from Setup.php that are derived from wgScriptPath
1165 'wgScript' => "$scriptPath/index.php",
1166 'wgLoadScript' => "$scriptPath/load.php",
1167 'wgStylePath' => "$scriptPath/skins",
1168 'wgLocalStylePath' => "$scriptPath/skins",
1169 'wgExtensionAssetsPath' => "$scriptPath/extensions",
1170 'wgUploadPath' => "$scriptPath/images",
1171 'wgResourceBasePath' => "$scriptPath",
1172 ];
1173 }
1174 return [];
1175 }
1176
1180 protected function envGetDefaultServer() {
1181 $assumeProxiesUseDefaultProtocolPorts =
1182 $this->getVar( 'wgAssumeProxiesUseDefaultProtocolPorts' );
1183
1184 return WebRequest::detectServer( $assumeProxiesUseDefaultProtocolPorts );
1185 }
1186
1190 public function getDefaultServer() {
1191 return $this->envGetDefaultServer();
1192 }
1193
1197 private function outputLS() {
1198 $this->request->response()->header( 'Content-type: application/x-httpd-php' );
1199 $this->request->response()->header(
1200 'Content-Disposition: attachment; filename="LocalSettings.php"'
1201 );
1202
1204 $rightsProfile = $this->rightsProfiles[$this->getVar( '_RightsProfile' )];
1205 foreach ( $rightsProfile as $group => $rightsArr ) {
1206 $ls->setGroupRights( $group, $rightsArr );
1207 }
1208 echo $ls->getText();
1209 }
1210
1214 public function outputCss() {
1215 $this->request->response()->header( 'Content-type: text/css' );
1216 echo $this->output->getCSS();
1217 }
1218
1222 public function getPhpErrors() {
1223 return $this->phpErrors;
1224 }
1225
1232 public function needsUpgrade() {
1233 return $this->getDBInstaller()->needsUpgrade();
1234 }
1235
1241 public function doUpgrade() {
1242 $dbInstaller = $this->getDBInstaller();
1243 $dbInstaller->preUpgrade();
1244
1245 $taskList = new TaskList;
1246 $taskFactory = $this->getTaskFactory();
1247 $taskFactory->registerWebUpgradeTasks( $taskList );
1248 $taskRunner = new TaskRunner( $taskList, $taskFactory, TaskFactory::PROFILE_WEB_UPGRADE );
1249
1250 ob_start( $this->outputHandler( ... ) );
1251 try {
1252 $status = $taskRunner->execute();
1253 $ret = $status->isOK();
1254
1255 $this->setVar( '_UpgradeDone', true );
1256 } catch ( Exception $e ) {
1257 // TODO: Should this use MWExceptionRenderer?
1258 echo "\nAn error occurred:\n";
1259 echo $e->getMessage();
1260 $ret = false;
1261 }
1262 ob_end_flush();
1263
1264 return $ret;
1265 }
1266
1267 public function outputHandler( $string ) {
1268 return htmlspecialchars( $string );
1269 }
1270
1271}
const MW_VERSION
The running version of MediaWiki.
Definition Defines.php:37
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
Definition Setup.php:559
Group all the pieces relevant to the context of a request into one instance.
This class is a collection of static functions that serve two purposes:
Definition Html.php:57
static getLocalSettingsGenerator(Installer $installer)
Instantiates and returns an instance of LocalSettingsGenerator or its descendant classes.
Base installer class.
Definition Installer.php:84
setVar( $name, $value)
Set a MW configuration variable, or internal installer configuration variable.
getFakePassword( $realPassword)
Get a fake password for sending back to the user in HTML.
disableTimeLimit()
Disable the time limit for execution.
setPassword( $name, $value)
Set a variable which stores a password, except if the new value is a fake password in which case leav...
parse( $text, $lineStart=false)
Convert wikitext $text to HTML.
getDBInstaller( $type=false)
Get an instance of DatabaseInstaller for the specified DB type.
getVar( $name, $default=null)
Get an MW configuration variable, or internal installer configuration variable.
Factory for installer tasks.
A container for tasks, with sorting of tasks by their declared dependencies.
Definition TaskList.php:13
Output class modelled on OutputPage.
Class for the core installer web interface.
int $tabIndex
Numeric index of the page we're on.
string[] $otherPages
Out of sequence pages, selectable by the user at any time.
detectWebPaths()
This is overridden by the web installer to provide the detected wgScriptPath.
getPageByName( $pageName)
Get a WebInstallerPage by name.
getLocalSettingsLocation()
If the software package wants the LocalSettings.php file to be placed in a specific location,...
errorHandler( $errno, $errstr)
Temporary error handler for session start debugging.
outputCss()
Output stylesheet for web installer pages.
showStatusMessage(Status $status)
Show a message to the installing user by using a Status object.
needsUpgrade()
Determine whether the current database needs to be upgraded, i.e.
string $currentPageName
Name of the page we're on.
array[] $session
Cached session array.
showSuccess( $msg,... $params)
Display a success message.
getUrl( $query=[])
Get a URL for submission back to the same script.
getFingerprint()
Get a hash of data identifying this MW installation.
makeLinkItem( $url, $linkText)
Helper for sidebar links.
string[] $pageSequence
The main sequence of page names.
getTextArea( $params)
Get a labelled textarea to configure a variable.
setupLanguage()
Initializes language-related variables.
reset()
We're restarting the installation, reset the session, happyPages, etc.
getRadioSet( $params)
Get a set of labelled radio buttons.
setSession( $name, $value)
Set a session variable.
getSession( $name, $default=null)
Get a session variable.
finish()
Clean up from execute()
label( $msg, $forId, $contents, $helpData="")
Label a control by wrapping a config-input div around it and putting a label before it.
startSession()
Start the PHP session.
__construct(WebRequest $request)
getRadioElements( $params)
Get a set of labelled radio buttons.
setVarsFromRequest( $varNames, $prefix='config_')
Convenience function to set variables based on form data.
getPasswordBox( $params)
Get a labelled password box to configure a variable.
getTextBox( $params)
Get a labelled text box to configure a variable.
getHelpBox( $msg,... $params)
Get small text indented help for a preceding form field.
bool $showSessionWarning
Flag indicating that session data may have been lost.
execute(array $session)
Main entry point.
int $helpBoxId
Numeric index of the help box.
getDocUrl( $page)
Helper for WebInstallerOutput.
bool[] $skippedPages
List of "skipped" pages.
showStatusBox( $status)
Output an error or warning box using a Status object.
WebRequest $request
WebRequest object.
getAcceptLanguage()
Retrieves MediaWiki language from Accept-Language HTTP header.
getInfoBox( $text)
Get HTML for an information message box.
string[] $phpErrors
Captured PHP error text.
showWarning( $msg,... $params)
Display a warning message.
doUpgrade()
Perform database upgrades.
getCheckBox( $params)
Get a labelled checkbox to configure a boolean variable.
bool[] $happyPages
Array of pages which have declared that they have been submitted, have validated their input,...
showMessage( $msg,... $params)
Display a short neutral message.
nextTabIndex()
Get the next tabindex attribute value.
getLowestUnhappy()
Find the next page in sequence that hasn't been completed.
showError( $msg,... $params)
Display an error message.
A service that provides utilities to do with language names and codes.
Service locator for MediaWiki core services.
static getInstance()
Returns the global default instance of the top level service locator.
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition Message.php:157
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form,...
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition Status.php:54
getMessages(?string $type=null)
Returns a list of error messages, optionally only those of the given type.
Marks HTML that shouldn't be escaped.
Definition HtmlArmor.php:32
$wgLanguageCode
Config variable stub for the LanguageCode setting, for use by phpdoc and IDEs.
element(SerializerNode $parent, SerializerNode $node, $contents)