MediaWiki  master
WebInstaller.php
Go to the documentation of this file.
1 <?php
27 
34 class WebInstaller extends Installer {
35 
39  public $output;
40 
46  public $request;
47 
53  protected $session;
54 
60  protected $phpErrors;
61 
72  public $pageSequence = [
73  'Language',
74  'ExistingWiki',
75  'Welcome',
76  'DBConnect',
77  'Upgrade',
78  'DBSettings',
79  'Name',
80  'Options',
81  'Install',
82  'Complete',
83  ];
84 
90  protected $otherPages = [
91  'Restart',
92  'ReleaseNotes',
93  'Copying',
94  'UpgradeDoc', // Can't use Upgrade due to Upgrade step
95  ];
96 
103  protected $happyPages;
104 
112  protected $skippedPages;
113 
119  public $showSessionWarning = false;
120 
126  protected $tabIndex = 1;
127 
133  protected $helpBoxId = 1;
134 
140  protected $currentPageName;
141 
145  public function __construct( WebRequest $request ) {
146  parent::__construct();
147  $this->output = new WebInstallerOutput( $this );
148  $this->request = $request;
149  }
150 
158  public function execute( array $session ) {
159  $this->session = $session;
160 
161  if ( isset( $session['settings'] ) ) {
162  $this->settings = $session['settings'] + $this->settings;
163  // T187586 MediaWikiServices works with globals
164  foreach ( $this->settings as $key => $val ) {
165  $GLOBALS[$key] = $val;
166  }
167  }
168 
169  $this->setupLanguage();
170 
171  if ( ( $this->getVar( '_InstallDone' ) || $this->getVar( '_UpgradeDone' ) )
172  && $this->request->getVal( 'localsettings' )
173  ) {
174  $this->outputLS();
175  return $this->session;
176  }
177 
178  $isCSS = $this->request->getVal( 'css' );
179  if ( $isCSS ) {
180  $this->outputCss();
181  return $this->session;
182  }
183 
184  $this->happyPages = $session['happyPages'] ?? [];
185 
186  $this->skippedPages = $session['skippedPages'] ?? [];
187 
188  $lowestUnhappy = $this->getLowestUnhappy();
189 
190  # Special case for Creative Commons partner chooser box.
191  if ( $this->request->getVal( 'SubmitCC' ) ) {
193  $page = $this->getPageByName( 'Options' );
194  '@phan-var WebInstallerOptions $page';
195  $this->output->useShortHeader();
196  $this->output->allowFrames();
197  $page->submitCC();
198 
199  return $this->finish();
200  }
201 
202  if ( $this->request->getVal( 'ShowCC' ) ) {
204  $page = $this->getPageByName( 'Options' );
205  '@phan-var WebInstallerOptions $page';
206  $this->output->useShortHeader();
207  $this->output->allowFrames();
208  $this->output->addHTML( $page->getCCDoneBox() );
209 
210  return $this->finish();
211  }
212 
213  # Get the page name.
214  $pageName = $this->request->getVal( 'page', '' );
215 
216  if ( in_array( $pageName, $this->otherPages ) ) {
217  # Out of sequence
218  $pageId = false;
219  $page = $this->getPageByName( $pageName );
220  } else {
221  # Main sequence
222  if ( !$pageName || !in_array( $pageName, $this->pageSequence ) ) {
223  $pageId = $lowestUnhappy;
224  } else {
225  $pageId = array_search( $pageName, $this->pageSequence );
226  }
227 
228  # If necessary, move back to the lowest-numbered unhappy page
229  if ( $pageId > $lowestUnhappy ) {
230  $pageId = $lowestUnhappy;
231  if ( $lowestUnhappy == 0 ) {
232  # Knocked back to start, possible loss of session data.
233  $this->showSessionWarning = true;
234  }
235  }
236 
237  $pageName = $this->pageSequence[$pageId];
238  $page = $this->getPageByName( $pageName );
239  }
240 
241  # If a back button was submitted, go back without submitting the form data.
242  if ( $this->request->wasPosted() && $this->request->getBool( 'submit-back' ) ) {
243  if ( $this->request->getVal( 'lastPage' ) ) {
244  $nextPage = $this->request->getVal( 'lastPage' );
245  } elseif ( $pageId !== false ) {
246  # Main sequence page
247  # Skip the skipped pages
248  $nextPageId = $pageId;
249 
250  do {
251  $nextPageId--;
252  $nextPage = $this->pageSequence[$nextPageId];
253  } while ( isset( $this->skippedPages[$nextPage] ) );
254  } else {
255  $nextPage = $this->pageSequence[$lowestUnhappy];
256  }
257 
258  $this->output->redirect( $this->getUrl( [ 'page' => $nextPage ] ) );
259 
260  return $this->finish();
261  }
262 
263  # Execute the page.
264  $this->currentPageName = $page->getName();
265  $this->startPageWrapper( $pageName );
266 
267  if ( $page->isSlow() ) {
268  $this->disableTimeLimit();
269  }
270 
271  $result = $page->execute();
272 
273  $this->endPageWrapper();
274 
275  if ( $result == 'skip' ) {
276  # Page skipped without explicit submission.
277  # Skip it when we click "back" so that we don't just go forward again.
278  $this->skippedPages[$pageName] = true;
279  $result = 'continue';
280  } else {
281  unset( $this->skippedPages[$pageName] );
282  }
283 
284  # If it was posted, the page can request a continue to the next page.
285  if ( $result === 'continue' && !$this->output->headerDone() ) {
286  if ( $pageId !== false ) {
287  $this->happyPages[$pageId] = true;
288  }
289 
290  $lowestUnhappy = $this->getLowestUnhappy();
291 
292  if ( $this->request->getVal( 'lastPage' ) ) {
293  $nextPage = $this->request->getVal( 'lastPage' );
294  } elseif ( $pageId !== false ) {
295  $nextPage = $this->pageSequence[$pageId + 1];
296  } else {
297  $nextPage = $this->pageSequence[$lowestUnhappy];
298  }
299 
300  if ( array_search( $nextPage, $this->pageSequence ) > $lowestUnhappy ) {
301  $nextPage = $this->pageSequence[$lowestUnhappy];
302  }
303 
304  $this->output->redirect( $this->getUrl( [ 'page' => $nextPage ] ) );
305  }
306 
307  return $this->finish();
308  }
309 
314  public function getLowestUnhappy() {
315  if ( count( $this->happyPages ) == 0 ) {
316  return 0;
317  } else {
318  return max( array_keys( $this->happyPages ) ) + 1;
319  }
320  }
321 
328  public function startSession() {
329  if ( wfIniGetBool( 'session.auto_start' ) || session_id() ) {
330  // Done already
331  return true;
332  }
333 
334  // Use secure cookies if we are on HTTPS
335  $options = [];
336  if ( $this->request->getProtocol() === 'https' ) {
337  $options['cookie_secure'] = '1';
338  }
339 
340  $this->phpErrors = [];
341  set_error_handler( [ $this, 'errorHandler' ] );
342  try {
343  session_name( 'mw_installer_session' );
344  session_start( $options );
345  } catch ( Exception $e ) {
346  restore_error_handler();
347  throw $e;
348  }
349  restore_error_handler();
350 
351  if ( $this->phpErrors ) {
352  return false;
353  }
354 
355  return true;
356  }
357 
366  public function getFingerprint() {
367  // Get the base URL of the installation
368  $url = $this->request->getFullRequestURL();
369  if ( preg_match( '!^(.*\?)!', $url, $m ) ) {
370  // Trim query string
371  $url = $m[1];
372  }
373  if ( preg_match( '!^(.*)/[^/]*/[^/]*$!', $url, $m ) ) {
374  // This... seems to try to get the base path from
375  // the /mw-config/index.php. Kinda scary though?
376  $url = $m[1];
377  }
378 
379  return md5( serialize( [
380  'local path' => dirname( __DIR__ ),
381  'url' => $url,
382  'version' => MW_VERSION
383  ] ) );
384  }
385 
392  public function showError( $msg, ...$params ) {
393  if ( !( $msg instanceof Message ) ) {
394  $msg = wfMessage(
395  $msg,
396  array_map( 'htmlspecialchars', $params )
397  );
398  }
399  $text = $msg->useDatabase( false )->parse();
400  $box = Html::errorBox( $text, '', 'config-error-box' );
401  $this->output->addHTML( $box );
402  }
403 
410  public function errorHandler( $errno, $errstr ) {
411  $this->phpErrors[] = $errstr;
412  }
413 
419  public function finish() {
420  $this->output->output();
421 
422  $this->session['happyPages'] = $this->happyPages;
423  $this->session['skippedPages'] = $this->skippedPages;
424  $this->session['settings'] = $this->settings;
425 
426  return $this->session;
427  }
428 
432  public function reset() {
433  $this->session = [];
434  $this->happyPages = [];
435  $this->settings = [];
436  }
437 
445  public function getUrl( $query = [] ) {
446  $url = $this->request->getRequestURL();
447  # Remove existing query
448  $url = preg_replace( '/\?.*$/', '', $url );
449 
450  if ( $query ) {
451  $url .= '?' . wfArrayToCgi( $query );
452  }
453 
454  return $url;
455  }
456 
463  public function getPageByName( $pageName ) {
464  $pageClass = 'WebInstaller' . $pageName;
465 
466  return new $pageClass( $this );
467  }
468 
477  public function getSession( $name, $default = null ) {
478  return $this->session[$name] ?? $default;
479  }
480 
487  public function setSession( $name, $value ) {
488  $this->session[$name] = $value;
489  }
490 
496  public function nextTabIndex() {
497  return $this->tabIndex++;
498  }
499 
503  public function setupLanguage() {
504  global $wgLang, $wgLanguageCode;
505 
506  if ( $this->getSession( 'test' ) === null && !$this->request->wasPosted() ) {
508  $wgLang = MediaWikiServices::getInstance()->getLanguageFactory()
509  ->getLanguage( $wgLanguageCode );
510  RequestContext::getMain()->setLanguage( $wgLang );
511  $this->setVar( 'wgLanguageCode', $wgLanguageCode );
512  $this->setVar( '_UserLang', $wgLanguageCode );
513  } else {
514  $wgLanguageCode = $this->getVar( 'wgLanguageCode' );
515  }
516  }
517 
524  public function getAcceptLanguage() {
525  global $wgLanguageCode, $wgRequest;
526 
527  $mwLanguages = MediaWikiServices::getInstance()
528  ->getLanguageNameUtils()
529  ->getLanguageNames( LanguageNameUtils::AUTONYMS, LanguageNameUtils::SUPPORTED );
530  $headerLanguages = array_keys( $wgRequest->getAcceptLang() );
531 
532  foreach ( $headerLanguages as $lang ) {
533  if ( isset( $mwLanguages[$lang] ) ) {
534  return $lang;
535  }
536  }
537 
538  return $wgLanguageCode;
539  }
540 
546  private function startPageWrapper( $currentPageName ) {
547  $s = "<div class=\"config-page-wrapper\">\n";
548  $s .= "<div class=\"config-page\">\n";
549  $s .= "<div class=\"config-page-list\"><ul>\n";
550  $lastHappy = -1;
551 
552  foreach ( $this->pageSequence as $id => $pageName ) {
553  $happy = !empty( $this->happyPages[$id] );
554  $s .= $this->getPageListItem(
555  $pageName,
556  $happy || $lastHappy == $id - 1,
558  );
559 
560  if ( $happy ) {
561  $lastHappy = $id;
562  }
563  }
564 
565  $s .= "</ul><br/><ul>\n";
566  $s .= $this->getPageListItem( 'Restart', true, $currentPageName );
567  // End list pane
568  $s .= "</ul></div>\n";
569 
570  // Messages:
571  // config-page-language, config-page-welcome, config-page-dbconnect, config-page-upgrade,
572  // config-page-dbsettings, config-page-name, config-page-options, config-page-install,
573  // config-page-complete, config-page-restart, config-page-releasenotes,
574  // config-page-copying, config-page-upgradedoc, config-page-existingwiki
575  $s .= Html::element( 'h2', [],
576  wfMessage( 'config-page-' . strtolower( $currentPageName ) )->text() );
577 
578  $this->output->addHTMLNoFlush( $s );
579  }
580 
590  private function getPageListItem( $pageName, $enabled, $currentPageName ) {
591  $s = "<li class=\"config-page-list-item\">";
592 
593  // Messages:
594  // config-page-language, config-page-welcome, config-page-dbconnect, config-page-upgrade,
595  // config-page-dbsettings, config-page-name, config-page-options, config-page-install,
596  // config-page-complete, config-page-restart, config-page-releasenotes,
597  // config-page-copying, config-page-upgradedoc, config-page-existingwiki
598  $name = wfMessage( 'config-page-' . strtolower( $pageName ) )->text();
599 
600  if ( $enabled ) {
601  $query = [ 'page' => $pageName ];
602 
603  if ( !in_array( $pageName, $this->pageSequence ) ) {
604  if ( in_array( $currentPageName, $this->pageSequence ) ) {
605  $query['lastPage'] = $currentPageName;
606  }
607 
608  $link = Html::element( 'a',
609  [
610  'href' => $this->getUrl( $query )
611  ],
612  $name
613  );
614  } else {
615  $link = htmlspecialchars( $name );
616  }
617 
618  if ( $pageName == $currentPageName ) {
619  $s .= "<span class=\"config-page-current\">$link</span>";
620  } else {
621  $s .= $link;
622  }
623  } else {
624  $s .= Html::element( 'span',
625  [
626  'class' => 'config-page-disabled'
627  ],
628  $name
629  );
630  }
631 
632  $s .= "</li>\n";
633 
634  return $s;
635  }
636 
640  private function endPageWrapper() {
641  $this->output->addHTMLNoFlush(
642  "<div class=\"visualClear\"></div>\n" .
643  "</div>\n" .
644  "<div class=\"visualClear\"></div>\n" .
645  "</div>" );
646  }
647 
656  public function getInfoBox( $text, $icon = false, $class = '' ) {
657  $html = ( $text instanceof HtmlArmor ) ?
658  HtmlArmor::getHtml( $text ) :
659  $this->parse( $text, true );
660  $icon = ( !$icon ) ?
661  'images/info-32.png' :
662  'images/' . $icon;
663  $alt = wfMessage( 'config-information' )->text();
664 
665  return self::infoBox( $html, $icon, $alt, $class );
666  }
667 
677  public function getHelpBox( $msg, ...$args ) {
678  $args = array_map( 'htmlspecialchars', $args );
679  $text = wfMessage( $msg, $args )->useDatabase( false )->plain();
680  $html = $this->parse( $text, true );
681  $id = 'helpBox-' . $this->helpBoxId++;
682 
683  return "<div class=\"config-help-field-container\">\n" .
684  "<input type=\"checkbox\" class=\"config-help-field-checkbox\" id=\"$id\" />" .
685  "<label class=\"config-help-field-hint\" for=\"$id\" title=\"" .
686  wfMessage( 'config-help-tooltip' )->escaped() . "\">" .
687  wfMessage( 'config-help' )->escaped() . "</label>\n" .
688  "<div class=\"config-help-field-data\">" . $html . "</div>\n" .
689  "</div>\n";
690  }
691 
697  public function showHelpBox( $msg, ...$params ) {
698  $html = $this->getHelpBox( $msg, ...$params );
699  $this->output->addHTML( $html );
700  }
701 
709  public function showMessage( $msg, ...$params ) {
710  $html = '<div class="config-message">' .
711  $this->parse( wfMessage( $msg, $params )->useDatabase( false )->plain() ) .
712  "</div>\n";
713  $this->output->addHTML( $html );
714  }
715 
719  public function showStatusMessage( Status $status ) {
720  $errors = array_merge( $status->getErrorsArray(), $status->getWarningsArray() );
721  foreach ( $errors as $error ) {
722  $this->showMessage( ...$error );
723  }
724  }
725 
737  public function label( $msg, $forId, $contents, $helpData = "" ) {
738  if ( strval( $msg ) == '' ) {
739  $labelText = "\u{00A0}";
740  } else {
741  $labelText = wfMessage( $msg )->escaped();
742  }
743 
744  $attributes = [ 'class' => 'config-label' ];
745 
746  if ( $forId ) {
747  $attributes['for'] = $forId;
748  }
749 
750  return "<div class=\"config-block\">\n" .
751  " <div class=\"config-block-label\">\n" .
752  Xml::tags( 'label',
753  $attributes,
754  $labelText
755  ) . "\n" .
756  $helpData .
757  " </div>\n" .
758  " <div class=\"config-block-elements\">\n" .
759  $contents .
760  " </div>\n" .
761  "</div>\n";
762  }
763 
779  public function getTextBox( $params ) {
780  if ( !isset( $params['controlName'] ) ) {
781  $params['controlName'] = 'config_' . $params['var'];
782  }
783 
784  if ( !isset( $params['value'] ) ) {
785  $params['value'] = $this->getVar( $params['var'] );
786  }
787 
788  if ( !isset( $params['attribs'] ) ) {
789  $params['attribs'] = [];
790  }
791  if ( !isset( $params['help'] ) ) {
792  $params['help'] = "";
793  }
794 
795  return $this->label(
796  $params['label'],
797  $params['controlName'],
798  Xml::input(
799  $params['controlName'],
800  30, // intended to be overridden by CSS
801  $params['value'],
802  $params['attribs'] + [
803  'id' => $params['controlName'],
804  'class' => 'config-input-text',
805  'tabindex' => $this->nextTabIndex()
806  ]
807  ),
808  $params['help']
809  );
810  }
811 
826  public function getTextArea( $params ) {
827  if ( !isset( $params['controlName'] ) ) {
828  $params['controlName'] = 'config_' . $params['var'];
829  }
830 
831  if ( !isset( $params['value'] ) ) {
832  $params['value'] = $this->getVar( $params['var'] );
833  }
834 
835  if ( !isset( $params['attribs'] ) ) {
836  $params['attribs'] = [];
837  }
838  if ( !isset( $params['help'] ) ) {
839  $params['help'] = "";
840  }
841 
842  return $this->label(
843  $params['label'],
844  $params['controlName'],
846  $params['controlName'],
847  $params['value'],
848  30,
849  5,
850  $params['attribs'] + [
851  'id' => $params['controlName'],
852  'class' => 'config-input-text',
853  'tabindex' => $this->nextTabIndex()
854  ]
855  ),
856  $params['help']
857  );
858  }
859 
876  public function getPasswordBox( $params ) {
877  if ( !isset( $params['value'] ) ) {
878  $params['value'] = $this->getVar( $params['var'] );
879  }
880 
881  if ( !isset( $params['attribs'] ) ) {
882  $params['attribs'] = [];
883  }
884 
885  $params['value'] = $this->getFakePassword( $params['value'] );
886  $params['attribs']['type'] = 'password';
887 
888  return $this->getTextBox( $params );
889  }
890 
907  public function getCheckBox( $params ) {
908  if ( !isset( $params['controlName'] ) ) {
909  $params['controlName'] = 'config_' . $params['var'];
910  }
911 
912  if ( !isset( $params['value'] ) ) {
913  $params['value'] = $this->getVar( $params['var'] );
914  }
915 
916  if ( !isset( $params['attribs'] ) ) {
917  $params['attribs'] = [];
918  }
919  if ( !isset( $params['help'] ) ) {
920  $params['help'] = "";
921  }
922  if ( !isset( $params['labelAttribs'] ) ) {
923  $params['labelAttribs'] = [];
924  }
925  $labelText = $params['rawtext'] ?? $this->parse( wfMessage( $params['label'] )->plain() );
926 
927  return "<div class=\"config-input-check\">\n" .
928  $params['help'] .
929  Html::rawElement(
930  'label',
931  $params['labelAttribs'],
932  Xml::check(
933  $params['controlName'],
934  $params['value'],
935  $params['attribs'] + [
936  'id' => $params['controlName'],
937  'tabindex' => $this->nextTabIndex(),
938  ]
939  ) .
940  $labelText . "\n"
941  ) .
942  "</div>\n";
943  }
944 
965  public function getRadioSet( $params ) {
966  $items = $this->getRadioElements( $params );
967 
968  $label = $params['label'] ?? '';
969 
970  if ( !isset( $params['controlName'] ) ) {
971  $params['controlName'] = 'config_' . $params['var'];
972  }
973 
974  if ( !isset( $params['help'] ) ) {
975  $params['help'] = "";
976  }
977 
978  $s = "<ul>\n";
979  foreach ( $items as $item ) {
980  $s .= "<li>$item</li>\n";
981  }
982  $s .= "</ul>\n";
983 
984  return $this->label( $label, $params['controlName'], $s, $params['help'] );
985  }
986 
996  public function getRadioElements( $params ) {
997  if ( !isset( $params['controlName'] ) ) {
998  $params['controlName'] = 'config_' . $params['var'];
999  }
1000 
1001  if ( !isset( $params['value'] ) ) {
1002  $params['value'] = $this->getVar( $params['var'] );
1003  }
1004 
1005  $items = [];
1006 
1007  foreach ( $params['values'] as $value ) {
1008  $itemAttribs = [];
1009 
1010  if ( isset( $params['commonAttribs'] ) ) {
1011  $itemAttribs = $params['commonAttribs'];
1012  }
1013 
1014  if ( isset( $params['itemAttribs'][$value] ) ) {
1015  $itemAttribs = $params['itemAttribs'][$value] + $itemAttribs;
1016  }
1017 
1018  $checked = $value == $params['value'];
1019  $id = $params['controlName'] . '_' . $value;
1020  $itemAttribs['id'] = $id;
1021  $itemAttribs['tabindex'] = $this->nextTabIndex();
1022 
1023  $items[$value] =
1024  Xml::radio( $params['controlName'], $value, $checked, $itemAttribs ) .
1025  "\u{00A0}" .
1026  Xml::tags( 'label', [ 'for' => $id ], $this->parse(
1027  isset( $params['itemLabels'] ) ?
1028  wfMessage( $params['itemLabels'][$value] )->plain() :
1029  wfMessage( $params['itemLabelPrefix'] . strtolower( $value ) )->plain()
1030  ) );
1031  }
1032 
1033  return $items;
1034  }
1035 
1041  public function showStatusBox( $status ) {
1042  if ( !$status->isGood() ) {
1043  $html = $status->getHTML();
1044 
1045  if ( $status->isOK() ) {
1046  $box = Html::warningBox( $html, 'config-warning-box' );
1047  } else {
1048  $box = Html::errorBox( $html, '', 'config-error-box' );
1049  }
1050 
1051  $this->output->addHTML( $box );
1052  }
1053  }
1054 
1065  public function setVarsFromRequest( $varNames, $prefix = 'config_' ) {
1066  $newValues = [];
1067 
1068  foreach ( $varNames as $name ) {
1069  $value = $this->request->getVal( $prefix . $name );
1070  // T32524, do not trim passwords
1071  if ( $value !== null && stripos( $name, 'password' ) === false ) {
1072  $value = trim( $value );
1073  }
1074  $newValues[$name] = $value;
1075 
1076  if ( $value === null ) {
1077  // Checkbox?
1078  $this->setVar( $name, false );
1079  } elseif ( stripos( $name, 'password' ) !== false ) {
1080  $this->setPassword( $name, $value );
1081  } else {
1082  $this->setVar( $name, $value );
1083  }
1084  }
1085 
1086  return $newValues;
1087  }
1088 
1096  public function getDocUrl( $page ) {
1097  $query = [ 'page' => $page ];
1098 
1099  if ( in_array( $this->currentPageName, $this->pageSequence ) ) {
1100  $query['lastPage'] = $this->currentPageName;
1101  }
1102 
1103  return $this->getUrl( $query );
1104  }
1105 
1114  public function makeLinkItem( $url, $linkText ) {
1115  return Html::rawElement( 'li', [],
1116  Html::element( 'a', [ 'href' => $url ], $linkText )
1117  );
1118  }
1119 
1126  public function makeDownloadLinkHtml() {
1127  $anchor = Html::rawElement( 'a',
1128  [ 'href' => $this->getUrl( [ 'localsettings' => 1 ] ) ],
1129  wfMessage( 'config-download-localsettings' )->parse()
1130  );
1131 
1132  return Html::rawElement( 'div', [ 'class' => 'config-download-link' ], $anchor );
1133  }
1134 
1145  public function getLocalSettingsLocation() {
1146  return false;
1147  }
1148 
1152  public function envCheckPath() {
1153  // PHP_SELF isn't available sometimes, such as when PHP is CGI but
1154  // cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME
1155  // to get the path to the current script... hopefully it's reliable. SIGH
1156  $path = false;
1157  if ( !empty( $_SERVER['PHP_SELF'] ) ) {
1158  $path = $_SERVER['PHP_SELF'];
1159  } elseif ( !empty( $_SERVER['SCRIPT_NAME'] ) ) {
1160  $path = $_SERVER['SCRIPT_NAME'];
1161  }
1162  if ( $path === false ) {
1163  $this->showError( 'config-no-uri' );
1164  return false;
1165  }
1166 
1167  return parent::envCheckPath();
1168  }
1169 
1170  public function envPrepPath() {
1171  parent::envPrepPath();
1172  // PHP_SELF isn't available sometimes, such as when PHP is CGI but
1173  // cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME
1174  // to get the path to the current script... hopefully it's reliable. SIGH
1175  $path = false;
1176  if ( !empty( $_SERVER['PHP_SELF'] ) ) {
1177  $path = $_SERVER['PHP_SELF'];
1178  } elseif ( !empty( $_SERVER['SCRIPT_NAME'] ) ) {
1179  $path = $_SERVER['SCRIPT_NAME'];
1180  }
1181  if ( $path !== false ) {
1182  $scriptPath = preg_replace( '{^(.*)/(mw-)?config.*$}', '$1', $path );
1183 
1184  $this->setVar( 'wgScriptPath', "$scriptPath" );
1185  // Update variables set from Setup.php that are derived from wgScriptPath
1186  $this->setVar( 'wgScript', "$scriptPath/index.php" );
1187  $this->setVar( 'wgLoadScript', "$scriptPath/load.php" );
1188  $this->setVar( 'wgStylePath', "$scriptPath/skins" );
1189  $this->setVar( 'wgLocalStylePath', "$scriptPath/skins" );
1190  $this->setVar( 'wgExtensionAssetsPath', "$scriptPath/extensions" );
1191  $this->setVar( 'wgUploadPath', "$scriptPath/images" );
1192  $this->setVar( 'wgResourceBasePath', "$scriptPath" );
1193  }
1194  }
1195 
1199  protected function envGetDefaultServer() {
1200  $assumeProxiesUseDefaultProtocolPorts =
1201  $this->getVar( 'wgAssumeProxiesUseDefaultProtocolPorts' );
1202 
1203  return WebRequest::detectServer( $assumeProxiesUseDefaultProtocolPorts );
1204  }
1205 
1209  private function outputLS() {
1210  $this->request->response()->header( 'Content-type: application/x-httpd-php' );
1211  $this->request->response()->header(
1212  'Content-Disposition: attachment; filename="LocalSettings.php"'
1213  );
1214 
1216  $rightsProfile = $this->rightsProfiles[$this->getVar( '_RightsProfile' )];
1217  foreach ( $rightsProfile as $group => $rightsArr ) {
1218  $ls->setGroupRights( $group, $rightsArr );
1219  }
1220  echo $ls->getText();
1221  }
1222 
1226  public function outputCss() {
1227  $this->request->response()->header( 'Content-type: text/css' );
1228  echo $this->output->getCSS();
1229  }
1230 
1234  public function getPhpErrors() {
1235  return $this->phpErrors;
1236  }
1237 
1248  protected static function infoBox( $rawHtml, $icon, $alt, $class = '' ) {
1249  $s = Html::openElement( 'div', [ 'class' => 'mw-installer-box-left' ] ) .
1250  Html::element( 'img',
1251  [
1252  'src' => $icon,
1253  'alt' => $alt,
1254  ]
1255  ) .
1256  Html::closeElement( 'div' ) .
1257  Html::openElement( 'div', [ 'class' => 'mw-installer-box-right' ] ) .
1258  $rawHtml .
1259  Html::closeElement( 'div' ) .
1260  Html::element( 'div', [ 'style' => 'clear: left;' ], ' ' );
1261 
1262  return Html::warningBox( $s, $class )
1263  . Html::element( 'div', [ 'style' => 'clear: left;' ], ' ' );
1264  }
1265 
1266 }
const MW_VERSION
The running version of MediaWiki.
Definition: Defines.php:36
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.
global $wgRequest
Definition: Setup.php:399
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode) $wgLang
Definition: Setup.php:519
Marks HTML that shouldn't be escaped.
Definition: HtmlArmor.php:30
static getHtml( $input)
Provide a string or HtmlArmor object and get safe HTML back.
Definition: HtmlArmor.php:54
static getLocalSettingsGenerator(Installer $installer)
Instantiates and returns an instance of LocalSettingsGenerator or its descendant classes.
Base installer class.
Definition: Installer.php:60
parse( $text, $lineStart=false)
Convert wikitext $text to HTML.
Definition: Installer.php:794
setVar( $name, $value)
Set a MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:607
getFakePassword( $realPassword)
Get a fake password for sending back to the user in HTML.
Definition: Installer.php:738
disableTimeLimit()
Disable the time limit for execution.
Definition: Installer.php:2002
array $settings
Definition: Installer.php:79
setPassword( $name, $value)
Set a variable which stores a password, except if the new value is a fake password in which case leav...
Definition: Installer.php:749
getVar( $name, $default=null)
Get an MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:621
This class is a collection of static functions that serve two purposes:
Definition: Html.php:55
A service that provides utilities to do with language names and codes.
Service locator for MediaWiki core services.
The Message class deals with fetching and processing of interface message into a variety of formats.
Definition: Message.php:144
static getMain()
Get the RequestContext object associated with the main request.
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:46
getErrorsArray()
Get the list of errors (but not warnings)
Definition: Status.php:408
getWarningsArray()
Get the list of warnings (but not errors)
Definition: Status.php:420
Output class modelled on OutputPage.
Class for the core installer web interface.
makeDownloadLinkHtml()
Helper for "Download LocalSettings" link.
setupLanguage()
Initializes language-related variables.
WebInstallerOutput $output
finish()
Clean up from execute()
getTextBox( $params)
Get a labelled text box to configure a variable.
getAcceptLanguage()
Retrieves MediaWiki language from Accept-Language HTTP header.
nextTabIndex()
Get the next tabindex attribute value.
showStatusBox( $status)
Output an error or warning box using a Status object.
setVarsFromRequest( $varNames, $prefix='config_')
Convenience function to set variables based on form data.
getPageByName( $pageName)
Get a WebInstallerPage by name.
errorHandler( $errno, $errstr)
Temporary error handler for session start debugging.
bool[] $happyPages
Array of pages which have declared that they have been submitted, have validated their input,...
getSession( $name, $default=null)
Get a session variable.
outputCss()
Output stylesheet for web installer pages.
getLowestUnhappy()
Find the next page in sequence that hasn't been completed.
showHelpBox( $msg,... $params)
Output a help box.
label( $msg, $forId, $contents, $helpData="")
Label a control by wrapping a config-input div around it and putting a label before it.
execute(array $session)
Main entry point.
getLocalSettingsLocation()
If the software package wants the LocalSettings.php file to be placed in a specific location,...
getDocUrl( $page)
Helper for WebInstallerOutput.
bool[] $skippedPages
List of "skipped" pages.
getRadioElements( $params)
Get a set of labelled radio buttons.
showMessage( $msg,... $params)
Show a short informational message.
showError( $msg,... $params)
Show an error message in a box.
setSession( $name, $value)
Set a session variable.
reset()
We're restarting the installation, reset the session, happyPages, etc.
string $currentPageName
Name of the page we're on.
getHelpBox( $msg,... $args)
Get small text indented help for a preceding form field.
getRadioSet( $params)
Get a set of labelled radio buttons.
getPasswordBox( $params)
Get a labelled password box to configure a variable.
getInfoBox( $text, $icon=false, $class='')
Get HTML for an information message box with an icon.
WebRequest $request
WebRequest object.
__construct(WebRequest $request)
getTextArea( $params)
Get a labelled textarea to configure a variable.
getFingerprint()
Get a hash of data identifying this MW installation.
string[] $otherPages
Out of sequence pages, selectable by the user at any time.
string[] $pageSequence
The main sequence of page names.
string[] $phpErrors
Captured PHP error text.
static infoBox( $rawHtml, $icon, $alt, $class='')
Get HTML for an information message box with an icon.
bool $showSessionWarning
Flag indicating that session data may have been lost.
showStatusMessage(Status $status)
getCheckBox( $params)
Get a labelled checkbox to configure a boolean variable.
makeLinkItem( $url, $linkText)
Helper for sidebar links.
startSession()
Start the PHP session.
int $tabIndex
Numeric index of the page we're on.
array[] $session
Cached session array.
getUrl( $query=[])
Get a URL for submission back to the same script.
envPrepPath()
Environment prep for setting $IP and $wgScriptPath.
int $helpBoxId
Numeric index of the help box.
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:49
static detectServer( $assumeProxiesUseDefaultProtocolPorts=null)
Work out an appropriate URL prefix containing scheme and host, based on information detected from $_S...
Definition: WebRequest.php:268
static textarea( $name, $content, $cols=40, $rows=5, $attribs=[])
Shortcut for creating textareas.
Definition: Xml.php:652
static check( $name, $checked=false, $attribs=[])
Convenience function to build an HTML checkbox.
Definition: Xml.php:330
static input( $name, $size=false, $value=false, $attribs=[])
Convenience function to build an HTML text input field.
Definition: Xml.php:281
static tags( $element, $attribs, $contents)
Same as Xml::element(), but does not escape contents.
Definition: Xml.php:135
static radio( $name, $value, $checked=false, $attribs=[])
Convenience function to build an HTML radio button.
Definition: Xml.php:348
$wgLanguageCode
Config variable stub for the LanguageCode setting, for use by phpdoc and IDEs.
foreach( $mmfl['setupFiles'] as $fileName) if( $queue) if(empty( $mmfl['quiet'])) $s
if(!isset( $args[0])) $lang