MediaWiki  master
WebInstaller.php
Go to the documentation of this file.
1 <?php
29 
36 class WebInstaller extends Installer {
37 
41  public $output;
42 
48  public $request;
49 
55  protected $session;
56 
62  protected $phpErrors;
63 
74  public $pageSequence = [
75  'Language',
76  'ExistingWiki',
77  'Welcome',
78  'DBConnect',
79  'Upgrade',
80  'DBSettings',
81  'Name',
82  'Options',
83  'Install',
84  'Complete',
85  ];
86 
92  protected $otherPages = [
93  'Restart',
94  'ReleaseNotes',
95  'Copying',
96  'UpgradeDoc', // Can't use Upgrade due to Upgrade step
97  ];
98 
105  protected $happyPages;
106 
114  protected $skippedPages;
115 
121  public $showSessionWarning = false;
122 
128  protected $tabIndex = 1;
129 
135  protected $helpBoxId = 1;
136 
142  protected $currentPageName;
143 
147  public function __construct( WebRequest $request ) {
148  parent::__construct();
149  $this->output = new WebInstallerOutput( $this );
150  $this->request = $request;
151  }
152 
160  public function execute( array $session ) {
161  $this->session = $session;
162 
163  if ( isset( $session['settings'] ) ) {
164  $this->settings = $session['settings'] + $this->settings;
165  // T187586 MediaWikiServices works with globals
166  foreach ( $this->settings as $key => $val ) {
167  $GLOBALS[$key] = $val;
168  }
169  }
170 
171  $this->setupLanguage();
172 
173  if ( ( $this->getVar( '_InstallDone' ) || $this->getVar( '_UpgradeDone' ) )
174  && $this->request->getVal( 'localsettings' )
175  ) {
176  $this->outputLS();
177  return $this->session;
178  }
179 
180  $isCSS = $this->request->getVal( 'css' );
181  if ( $isCSS ) {
182  $this->outputCss();
183  return $this->session;
184  }
185 
186  $this->happyPages = $session['happyPages'] ?? [];
187 
188  $this->skippedPages = $session['skippedPages'] ?? [];
189 
190  $lowestUnhappy = $this->getLowestUnhappy();
191 
192  # Special case for Creative Commons partner chooser box.
193  if ( $this->request->getVal( 'SubmitCC' ) ) {
195  $page = $this->getPageByName( 'Options' );
196  '@phan-var WebInstallerOptions $page';
197  $this->output->useShortHeader();
198  $this->output->allowFrames();
199  $page->submitCC();
200 
201  return $this->finish();
202  }
203 
204  if ( $this->request->getVal( 'ShowCC' ) ) {
206  $page = $this->getPageByName( 'Options' );
207  '@phan-var WebInstallerOptions $page';
208  $this->output->useShortHeader();
209  $this->output->allowFrames();
210  $this->output->addHTML( $page->getCCDoneBox() );
211 
212  return $this->finish();
213  }
214 
215  # Get the page name.
216  $pageName = $this->request->getVal( 'page', '' );
217 
218  if ( in_array( $pageName, $this->otherPages ) ) {
219  # Out of sequence
220  $pageId = false;
221  $page = $this->getPageByName( $pageName );
222  } else {
223  # Main sequence
224  if ( !$pageName || !in_array( $pageName, $this->pageSequence ) ) {
225  $pageId = $lowestUnhappy;
226  } else {
227  $pageId = array_search( $pageName, $this->pageSequence );
228  }
229 
230  # If necessary, move back to the lowest-numbered unhappy page
231  if ( $pageId > $lowestUnhappy ) {
232  $pageId = $lowestUnhappy;
233  if ( $lowestUnhappy == 0 ) {
234  # Knocked back to start, possible loss of session data.
235  $this->showSessionWarning = true;
236  }
237  }
238 
239  $pageName = $this->pageSequence[$pageId];
240  $page = $this->getPageByName( $pageName );
241  }
242 
243  # If a back button was submitted, go back without submitting the form data.
244  if ( $this->request->wasPosted() && $this->request->getBool( 'submit-back' ) ) {
245  if ( $this->request->getVal( 'lastPage' ) ) {
246  $nextPage = $this->request->getVal( 'lastPage' );
247  } elseif ( $pageId !== false ) {
248  # Main sequence page
249  # Skip the skipped pages
250  $nextPageId = $pageId;
251 
252  do {
253  $nextPageId--;
254  $nextPage = $this->pageSequence[$nextPageId];
255  } while ( isset( $this->skippedPages[$nextPage] ) );
256  } else {
257  $nextPage = $this->pageSequence[$lowestUnhappy];
258  }
259 
260  $this->output->redirect( $this->getUrl( [ 'page' => $nextPage ] ) );
261 
262  return $this->finish();
263  }
264 
265  # Execute the page.
266  $this->currentPageName = $page->getName();
267  $this->startPageWrapper( $pageName );
268 
269  if ( $page->isSlow() ) {
270  $this->disableTimeLimit();
271  }
272 
273  $result = $page->execute();
274 
275  $this->endPageWrapper();
276 
277  if ( $result == 'skip' ) {
278  # Page skipped without explicit submission.
279  # Skip it when we click "back" so that we don't just go forward again.
280  $this->skippedPages[$pageName] = true;
281  $result = 'continue';
282  } else {
283  unset( $this->skippedPages[$pageName] );
284  }
285 
286  # If it was posted, the page can request a continue to the next page.
287  if ( $result === 'continue' && !$this->output->headerDone() ) {
288  if ( $pageId !== false ) {
289  $this->happyPages[$pageId] = true;
290  }
291 
292  $lowestUnhappy = $this->getLowestUnhappy();
293 
294  if ( $this->request->getVal( 'lastPage' ) ) {
295  $nextPage = $this->request->getVal( 'lastPage' );
296  } elseif ( $pageId !== false ) {
297  $nextPage = $this->pageSequence[$pageId + 1];
298  } else {
299  $nextPage = $this->pageSequence[$lowestUnhappy];
300  }
301 
302  if ( array_search( $nextPage, $this->pageSequence ) > $lowestUnhappy ) {
303  $nextPage = $this->pageSequence[$lowestUnhappy];
304  }
305 
306  $this->output->redirect( $this->getUrl( [ 'page' => $nextPage ] ) );
307  }
308 
309  return $this->finish();
310  }
311 
316  public function getLowestUnhappy() {
317  if ( count( $this->happyPages ) == 0 ) {
318  return 0;
319  } else {
320  return max( array_keys( $this->happyPages ) ) + 1;
321  }
322  }
323 
330  public function startSession() {
331  if ( wfIniGetBool( 'session.auto_start' ) || session_id() ) {
332  // Done already
333  return true;
334  }
335 
336  // Use secure cookies if we are on HTTPS
337  $options = [];
338  if ( $this->request->getProtocol() === 'https' ) {
339  $options['cookie_secure'] = '1';
340  }
341 
342  $this->phpErrors = [];
343  set_error_handler( [ $this, 'errorHandler' ] );
344  try {
345  session_name( 'mw_installer_session' );
346  session_start( $options );
347  } catch ( Exception $e ) {
348  restore_error_handler();
349  throw $e;
350  }
351  restore_error_handler();
352 
353  if ( $this->phpErrors ) {
354  return false;
355  }
356 
357  return true;
358  }
359 
368  public function getFingerprint() {
369  // Get the base URL of the installation
370  $url = $this->request->getFullRequestURL();
371  if ( preg_match( '!^(.*\?)!', $url, $m ) ) {
372  // Trim query string
373  $url = $m[1];
374  }
375  if ( preg_match( '!^(.*)/[^/]*/[^/]*$!', $url, $m ) ) {
376  // This... seems to try to get the base path from
377  // the /mw-config/index.php. Kinda scary though?
378  $url = $m[1];
379  }
380 
381  return md5( serialize( [
382  'local path' => dirname( __DIR__ ),
383  'url' => $url,
384  'version' => MW_VERSION
385  ] ) );
386  }
387 
394  public function showError( $msg, ...$params ) {
395  if ( !( $msg instanceof Message ) ) {
396  $msg = wfMessage(
397  $msg,
398  array_map( 'htmlspecialchars', $params )
399  );
400  }
401  $text = $msg->useDatabase( false )->parse();
402  $box = Html::errorBox( $text, '', 'config-error-box' );
403  $this->output->addHTML( $box );
404  }
405 
412  public function errorHandler( $errno, $errstr ) {
413  $this->phpErrors[] = $errstr;
414  }
415 
421  public function finish() {
422  $this->output->output();
423 
424  $this->session['happyPages'] = $this->happyPages;
425  $this->session['skippedPages'] = $this->skippedPages;
426  $this->session['settings'] = $this->settings;
427 
428  return $this->session;
429  }
430 
434  public function reset() {
435  $this->session = [];
436  $this->happyPages = [];
437  $this->settings = [];
438  }
439 
447  public function getUrl( $query = [] ) {
448  $url = $this->request->getRequestURL();
449  # Remove existing query
450  $url = preg_replace( '/\?.*$/', '', $url );
451 
452  if ( $query ) {
453  $url .= '?' . wfArrayToCgi( $query );
454  }
455 
456  return $url;
457  }
458 
465  public function getPageByName( $pageName ) {
466  $pageClass = 'WebInstaller' . $pageName;
467 
468  return new $pageClass( $this );
469  }
470 
479  public function getSession( $name, $default = null ) {
480  return $this->session[$name] ?? $default;
481  }
482 
489  public function setSession( $name, $value ) {
490  $this->session[$name] = $value;
491  }
492 
498  public function nextTabIndex() {
499  return $this->tabIndex++;
500  }
501 
505  public function setupLanguage() {
506  global $wgLang, $wgLanguageCode;
507 
508  if ( $this->getSession( 'test' ) === null && !$this->request->wasPosted() ) {
510  $wgLang = MediaWikiServices::getInstance()->getLanguageFactory()
511  ->getLanguage( $wgLanguageCode );
512  RequestContext::getMain()->setLanguage( $wgLang );
513  $this->setVar( 'wgLanguageCode', $wgLanguageCode );
514  $this->setVar( '_UserLang', $wgLanguageCode );
515  } else {
516  $wgLanguageCode = $this->getVar( 'wgLanguageCode' );
517  }
518  }
519 
526  public function getAcceptLanguage() {
527  global $wgLanguageCode, $wgRequest;
528 
529  $mwLanguages = MediaWikiServices::getInstance()
530  ->getLanguageNameUtils()
531  ->getLanguageNames( LanguageNameUtils::AUTONYMS, LanguageNameUtils::SUPPORTED );
532  $headerLanguages = array_keys( $wgRequest->getAcceptLang() );
533 
534  foreach ( $headerLanguages as $lang ) {
535  if ( isset( $mwLanguages[$lang] ) ) {
536  return $lang;
537  }
538  }
539 
540  return $wgLanguageCode;
541  }
542 
548  private function startPageWrapper( $currentPageName ) {
549  $s = "<div class=\"config-page-wrapper\">\n";
550  $s .= "<div class=\"config-page\">\n";
551  $s .= "<div class=\"config-page-list\"><ul>\n";
552  $lastHappy = -1;
553 
554  foreach ( $this->pageSequence as $id => $pageName ) {
555  $happy = !empty( $this->happyPages[$id] );
556  $s .= $this->getPageListItem(
557  $pageName,
558  $happy || $lastHappy == $id - 1,
560  );
561 
562  if ( $happy ) {
563  $lastHappy = $id;
564  }
565  }
566 
567  $s .= "</ul><br/><ul>\n";
568  $s .= $this->getPageListItem( 'Restart', true, $currentPageName );
569  // End list pane
570  $s .= "</ul></div>\n";
571 
572  // Messages:
573  // config-page-language, config-page-welcome, config-page-dbconnect, config-page-upgrade,
574  // config-page-dbsettings, config-page-name, config-page-options, config-page-install,
575  // config-page-complete, config-page-restart, config-page-releasenotes,
576  // config-page-copying, config-page-upgradedoc, config-page-existingwiki
577  $s .= Html::element( 'h2', [],
578  wfMessage( 'config-page-' . strtolower( $currentPageName ) )->text() );
579 
580  $this->output->addHTMLNoFlush( $s );
581  }
582 
592  private function getPageListItem( $pageName, $enabled, $currentPageName ) {
593  $s = "<li class=\"config-page-list-item\">";
594 
595  // Messages:
596  // config-page-language, config-page-welcome, config-page-dbconnect, config-page-upgrade,
597  // config-page-dbsettings, config-page-name, config-page-options, config-page-install,
598  // config-page-complete, config-page-restart, config-page-releasenotes,
599  // config-page-copying, config-page-upgradedoc, config-page-existingwiki
600  $name = wfMessage( 'config-page-' . strtolower( $pageName ) )->text();
601 
602  if ( $enabled ) {
603  $query = [ 'page' => $pageName ];
604 
605  if ( !in_array( $pageName, $this->pageSequence ) ) {
606  if ( in_array( $currentPageName, $this->pageSequence ) ) {
607  $query['lastPage'] = $currentPageName;
608  }
609 
610  $link = Html::element( 'a',
611  [
612  'href' => $this->getUrl( $query )
613  ],
614  $name
615  );
616  } else {
617  $link = htmlspecialchars( $name );
618  }
619 
620  if ( $pageName == $currentPageName ) {
621  $s .= "<span class=\"config-page-current\">$link</span>";
622  } else {
623  $s .= $link;
624  }
625  } else {
626  $s .= Html::element( 'span',
627  [
628  'class' => 'config-page-disabled'
629  ],
630  $name
631  );
632  }
633 
634  $s .= "</li>\n";
635 
636  return $s;
637  }
638 
642  private function endPageWrapper() {
643  $this->output->addHTMLNoFlush(
644  "<div class=\"visualClear\"></div>\n" .
645  "</div>\n" .
646  "<div class=\"visualClear\"></div>\n" .
647  "</div>" );
648  }
649 
658  public function getInfoBox( $text, $icon = false, $class = '' ) {
659  $html = ( $text instanceof HtmlArmor ) ?
660  HtmlArmor::getHtml( $text ) :
661  $this->parse( $text, true );
662  $icon = ( !$icon ) ?
663  'images/info-32.png' :
664  'images/' . $icon;
665  $alt = wfMessage( 'config-information' )->text();
666 
667  return self::infoBox( $html, $icon, $alt, $class );
668  }
669 
679  public function getHelpBox( $msg, ...$args ) {
680  $args = array_map( 'htmlspecialchars', $args );
681  $text = wfMessage( $msg, $args )->useDatabase( false )->plain();
682  $html = $this->parse( $text, true );
683  $id = 'helpBox-' . $this->helpBoxId++;
684 
685  return "<div class=\"config-help-field-container\">\n" .
686  "<input type=\"checkbox\" class=\"config-help-field-checkbox\" id=\"$id\" />" .
687  "<label class=\"config-help-field-hint\" for=\"$id\" title=\"" .
688  wfMessage( 'config-help-tooltip' )->escaped() . "\">" .
689  wfMessage( 'config-help' )->escaped() . "</label>\n" .
690  "<div class=\"config-help-field-data\">" . $html . "</div>\n" .
691  "</div>\n";
692  }
693 
699  public function showHelpBox( $msg, ...$params ) {
700  $html = $this->getHelpBox( $msg, ...$params );
701  $this->output->addHTML( $html );
702  }
703 
711  public function showMessage( $msg, ...$params ) {
712  $html = '<div class="config-message">' .
713  $this->parse( wfMessage( $msg, $params )->useDatabase( false )->plain() ) .
714  "</div>\n";
715  $this->output->addHTML( $html );
716  }
717 
721  public function showStatusMessage( Status $status ) {
722  $errors = array_merge( $status->getErrorsArray(), $status->getWarningsArray() );
723  foreach ( $errors as $error ) {
724  $this->showMessage( ...$error );
725  }
726  }
727 
739  public function label( $msg, $forId, $contents, $helpData = "" ) {
740  if ( strval( $msg ) == '' ) {
741  $labelText = "\u{00A0}";
742  } else {
743  $labelText = wfMessage( $msg )->escaped();
744  }
745 
746  $attributes = [ 'class' => 'config-label' ];
747 
748  if ( $forId ) {
749  $attributes['for'] = $forId;
750  }
751 
752  return "<div class=\"config-block\">\n" .
753  " <div class=\"config-block-label\">\n" .
754  Xml::tags( 'label',
755  $attributes,
756  $labelText
757  ) . "\n" .
758  $helpData .
759  " </div>\n" .
760  " <div class=\"config-block-elements\">\n" .
761  $contents .
762  " </div>\n" .
763  "</div>\n";
764  }
765 
781  public function getTextBox( $params ) {
782  if ( !isset( $params['controlName'] ) ) {
783  $params['controlName'] = 'config_' . $params['var'];
784  }
785 
786  if ( !isset( $params['value'] ) ) {
787  $params['value'] = $this->getVar( $params['var'] );
788  }
789 
790  if ( !isset( $params['attribs'] ) ) {
791  $params['attribs'] = [];
792  }
793  if ( !isset( $params['help'] ) ) {
794  $params['help'] = "";
795  }
796 
797  return $this->label(
798  $params['label'],
799  $params['controlName'],
800  Xml::input(
801  $params['controlName'],
802  30, // intended to be overridden by CSS
803  $params['value'],
804  $params['attribs'] + [
805  'id' => $params['controlName'],
806  'class' => 'config-input-text',
807  'tabindex' => $this->nextTabIndex()
808  ]
809  ),
810  $params['help']
811  );
812  }
813 
828  public function getTextArea( $params ) {
829  if ( !isset( $params['controlName'] ) ) {
830  $params['controlName'] = 'config_' . $params['var'];
831  }
832 
833  if ( !isset( $params['value'] ) ) {
834  $params['value'] = $this->getVar( $params['var'] );
835  }
836 
837  if ( !isset( $params['attribs'] ) ) {
838  $params['attribs'] = [];
839  }
840  if ( !isset( $params['help'] ) ) {
841  $params['help'] = "";
842  }
843 
844  return $this->label(
845  $params['label'],
846  $params['controlName'],
848  $params['controlName'],
849  $params['value'],
850  30,
851  5,
852  $params['attribs'] + [
853  'id' => $params['controlName'],
854  'class' => 'config-input-text',
855  'tabindex' => $this->nextTabIndex()
856  ]
857  ),
858  $params['help']
859  );
860  }
861 
878  public function getPasswordBox( $params ) {
879  if ( !isset( $params['value'] ) ) {
880  $params['value'] = $this->getVar( $params['var'] );
881  }
882 
883  if ( !isset( $params['attribs'] ) ) {
884  $params['attribs'] = [];
885  }
886 
887  $params['value'] = $this->getFakePassword( $params['value'] );
888  $params['attribs']['type'] = 'password';
889 
890  return $this->getTextBox( $params );
891  }
892 
909  public function getCheckBox( $params ) {
910  if ( !isset( $params['controlName'] ) ) {
911  $params['controlName'] = 'config_' . $params['var'];
912  }
913 
914  if ( !isset( $params['value'] ) ) {
915  $params['value'] = $this->getVar( $params['var'] );
916  }
917 
918  if ( !isset( $params['attribs'] ) ) {
919  $params['attribs'] = [];
920  }
921  if ( !isset( $params['help'] ) ) {
922  $params['help'] = "";
923  }
924  if ( !isset( $params['labelAttribs'] ) ) {
925  $params['labelAttribs'] = [];
926  }
927  $labelText = $params['rawtext'] ?? $this->parse( wfMessage( $params['label'] )->plain() );
928 
929  return "<div class=\"config-input-check\">\n" .
930  $params['help'] .
931  Html::rawElement(
932  'label',
933  $params['labelAttribs'],
934  Xml::check(
935  $params['controlName'],
936  $params['value'],
937  $params['attribs'] + [
938  'id' => $params['controlName'],
939  'tabindex' => $this->nextTabIndex(),
940  ]
941  ) .
942  $labelText . "\n"
943  ) .
944  "</div>\n";
945  }
946 
967  public function getRadioSet( $params ) {
968  $items = $this->getRadioElements( $params );
969 
970  $label = $params['label'] ?? '';
971 
972  if ( !isset( $params['controlName'] ) ) {
973  $params['controlName'] = 'config_' . $params['var'];
974  }
975 
976  if ( !isset( $params['help'] ) ) {
977  $params['help'] = "";
978  }
979 
980  $s = "<ul>\n";
981  foreach ( $items as $item ) {
982  $s .= "<li>$item</li>\n";
983  }
984  $s .= "</ul>\n";
985 
986  return $this->label( $label, $params['controlName'], $s, $params['help'] );
987  }
988 
998  public function getRadioElements( $params ) {
999  if ( !isset( $params['controlName'] ) ) {
1000  $params['controlName'] = 'config_' . $params['var'];
1001  }
1002 
1003  if ( !isset( $params['value'] ) ) {
1004  $params['value'] = $this->getVar( $params['var'] );
1005  }
1006 
1007  $items = [];
1008 
1009  foreach ( $params['values'] as $value ) {
1010  $itemAttribs = [];
1011 
1012  if ( isset( $params['commonAttribs'] ) ) {
1013  $itemAttribs = $params['commonAttribs'];
1014  }
1015 
1016  if ( isset( $params['itemAttribs'][$value] ) ) {
1017  $itemAttribs = $params['itemAttribs'][$value] + $itemAttribs;
1018  }
1019 
1020  $checked = $value == $params['value'];
1021  $id = $params['controlName'] . '_' . $value;
1022  $itemAttribs['id'] = $id;
1023  $itemAttribs['tabindex'] = $this->nextTabIndex();
1024 
1025  $items[$value] =
1026  Xml::radio( $params['controlName'], $value, $checked, $itemAttribs ) .
1027  "\u{00A0}" .
1028  Xml::tags( 'label', [ 'for' => $id ], $this->parse(
1029  isset( $params['itemLabels'] ) ?
1030  wfMessage( $params['itemLabels'][$value] )->plain() :
1031  wfMessage( $params['itemLabelPrefix'] . strtolower( $value ) )->plain()
1032  ) );
1033  }
1034 
1035  return $items;
1036  }
1037 
1043  public function showStatusBox( $status ) {
1044  if ( !$status->isGood() ) {
1045  $html = $status->getHTML();
1046 
1047  if ( $status->isOK() ) {
1048  $box = Html::warningBox( $html, 'config-warning-box' );
1049  } else {
1050  $box = Html::errorBox( $html, '', 'config-error-box' );
1051  }
1052 
1053  $this->output->addHTML( $box );
1054  }
1055  }
1056 
1067  public function setVarsFromRequest( $varNames, $prefix = 'config_' ) {
1068  $newValues = [];
1069 
1070  foreach ( $varNames as $name ) {
1071  $value = $this->request->getVal( $prefix . $name );
1072  // T32524, do not trim passwords
1073  if ( $value !== null && stripos( $name, 'password' ) === false ) {
1074  $value = trim( $value );
1075  }
1076  $newValues[$name] = $value;
1077 
1078  if ( $value === null ) {
1079  // Checkbox?
1080  $this->setVar( $name, false );
1081  } elseif ( stripos( $name, 'password' ) !== false ) {
1082  $this->setPassword( $name, $value );
1083  } else {
1084  $this->setVar( $name, $value );
1085  }
1086  }
1087 
1088  return $newValues;
1089  }
1090 
1098  public function getDocUrl( $page ) {
1099  $query = [ 'page' => $page ];
1100 
1101  if ( in_array( $this->currentPageName, $this->pageSequence ) ) {
1102  $query['lastPage'] = $this->currentPageName;
1103  }
1104 
1105  return $this->getUrl( $query );
1106  }
1107 
1116  public function makeLinkItem( $url, $linkText ) {
1117  return Html::rawElement( 'li', [],
1118  Html::element( 'a', [ 'href' => $url ], $linkText )
1119  );
1120  }
1121 
1128  public function makeDownloadLinkHtml() {
1129  $anchor = Html::rawElement( 'a',
1130  [ 'href' => $this->getUrl( [ 'localsettings' => 1 ] ) ],
1131  wfMessage( 'config-download-localsettings' )->parse()
1132  );
1133 
1134  return Html::rawElement( 'div', [ 'class' => 'config-download-link' ], $anchor );
1135  }
1136 
1147  public function getLocalSettingsLocation() {
1148  return false;
1149  }
1150 
1154  public function envCheckPath() {
1155  // PHP_SELF isn't available sometimes, such as when PHP is CGI but
1156  // cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME
1157  // to get the path to the current script... hopefully it's reliable. SIGH
1158  $path = false;
1159  if ( !empty( $_SERVER['PHP_SELF'] ) ) {
1160  $path = $_SERVER['PHP_SELF'];
1161  } elseif ( !empty( $_SERVER['SCRIPT_NAME'] ) ) {
1162  $path = $_SERVER['SCRIPT_NAME'];
1163  }
1164  if ( $path === false ) {
1165  $this->showError( 'config-no-uri' );
1166  return false;
1167  }
1168 
1169  return parent::envCheckPath();
1170  }
1171 
1172  public function envPrepPath() {
1173  parent::envPrepPath();
1174  // PHP_SELF isn't available sometimes, such as when PHP is CGI but
1175  // cgi.fix_pathinfo is disabled. In that case, fall back to SCRIPT_NAME
1176  // to get the path to the current script... hopefully it's reliable. SIGH
1177  $path = false;
1178  if ( !empty( $_SERVER['PHP_SELF'] ) ) {
1179  $path = $_SERVER['PHP_SELF'];
1180  } elseif ( !empty( $_SERVER['SCRIPT_NAME'] ) ) {
1181  $path = $_SERVER['SCRIPT_NAME'];
1182  }
1183  if ( $path !== false ) {
1184  $scriptPath = preg_replace( '{^(.*)/(mw-)?config.*$}', '$1', $path );
1185 
1186  $this->setVar( 'wgScriptPath', "$scriptPath" );
1187  // Update variables set from Setup.php that are derived from wgScriptPath
1188  $this->setVar( 'wgScript', "$scriptPath/index.php" );
1189  $this->setVar( 'wgLoadScript', "$scriptPath/load.php" );
1190  $this->setVar( 'wgStylePath', "$scriptPath/skins" );
1191  $this->setVar( 'wgLocalStylePath', "$scriptPath/skins" );
1192  $this->setVar( 'wgExtensionAssetsPath', "$scriptPath/extensions" );
1193  $this->setVar( 'wgUploadPath', "$scriptPath/images" );
1194  $this->setVar( 'wgResourceBasePath', "$scriptPath" );
1195  }
1196  }
1197 
1201  protected function envGetDefaultServer() {
1202  $assumeProxiesUseDefaultProtocolPorts =
1203  $this->getVar( 'wgAssumeProxiesUseDefaultProtocolPorts' );
1204 
1205  return WebRequest::detectServer( $assumeProxiesUseDefaultProtocolPorts );
1206  }
1207 
1211  private function outputLS() {
1212  $this->request->response()->header( 'Content-type: application/x-httpd-php' );
1213  $this->request->response()->header(
1214  'Content-Disposition: attachment; filename="LocalSettings.php"'
1215  );
1216 
1218  $rightsProfile = $this->rightsProfiles[$this->getVar( '_RightsProfile' )];
1219  foreach ( $rightsProfile as $group => $rightsArr ) {
1220  $ls->setGroupRights( $group, $rightsArr );
1221  }
1222  echo $ls->getText();
1223  }
1224 
1228  public function outputCss() {
1229  $this->request->response()->header( 'Content-type: text/css' );
1230  echo $this->output->getCSS();
1231  }
1232 
1236  public function getPhpErrors() {
1237  return $this->phpErrors;
1238  }
1239 
1250  protected static function infoBox( $rawHtml, $icon, $alt, $class = '' ) {
1251  $s = Html::openElement( 'div', [ 'class' => 'mw-installer-box-left' ] ) .
1252  Html::element( 'img',
1253  [
1254  'src' => $icon,
1255  'alt' => $alt,
1256  ]
1257  ) .
1258  Html::closeElement( 'div' ) .
1259  Html::openElement( 'div', [ 'class' => 'mw-installer-box-right' ] ) .
1260  $rawHtml .
1261  Html::closeElement( 'div' ) .
1262  Html::element( 'div', [ 'style' => 'clear: left;' ], ' ' );
1263 
1264  return Html::warningBox( $s, $class )
1265  . Html::element( 'div', [ 'style' => 'clear: left;' ], ' ' );
1266  }
1267 
1268 }
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:414
if(!defined( 'MW_NO_SESSION') &&! $wgCommandLineMode) $wgLang
Definition: Setup.php:535
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:66
parse( $text, $lineStart=false)
Convert wikitext $text to HTML.
Definition: Installer.php:785
setVar( $name, $value)
Set a MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:598
getFakePassword( $realPassword)
Get a fake password for sending back to the user in HTML.
Definition: Installer.php:729
disableTimeLimit()
Disable the time limit for execution.
Definition: Installer.php:1981
array $settings
Definition: Installer.php:77
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:740
getVar( $name, $default=null)
Get an MW configuration variable, or internal installer configuration variable.
Definition: Installer.php:612
This class is a collection of static functions that serve two purposes:
Definition: Html.php:57
A service that provides utilities to do with language names and codes.
Service locator for MediaWiki core services.
The WebRequest class encapsulates getting at data passed in the URL or via a POSTed form stripping il...
Definition: WebRequest.php:50
Generic operation result class Has warning/error list, boolean status and arbitrary value.
Definition: Status.php:58
getWarningsArray()
Get the list of warnings (but not errors)
Definition: Status.php:448
getErrorsArray()
Get the list of errors (but not warnings)
Definition: Status.php:437
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.
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.
static textarea( $name, $content, $cols=40, $rows=5, $attribs=[])
Shortcut for creating textareas.
Definition: Xml.php:650
static check( $name, $checked=false, $attribs=[])
Convenience function to build an HTML checkbox.
Definition: Xml.php:328
static input( $name, $size=false, $value=false, $attribs=[])
Convenience function to build an HTML text input field.
Definition: Xml.php:279
static tags( $element, $attribs, $contents)
Same as Xml::element(), but does not escape contents.
Definition: Xml.php:133
static radio( $name, $value, $checked=false, $attribs=[])
Convenience function to build an HTML radio button.
Definition: Xml.php:346
$wgLanguageCode
Config variable stub for the LanguageCode setting, for use by phpdoc and IDEs.