MediaWiki  master
WebInstallerOptions.php
Go to the documentation of this file.
1 <?php
24 use Wikimedia\IPUtils;
25 
27 
31  public function execute() {
32  if ( $this->getVar( '_SkipOptional' ) == 'skip' ) {
33  $this->submitSkins();
34  return 'skip';
35  }
36  if ( $this->parent->request->wasPosted() && $this->submit() ) {
37  return 'continue';
38  }
39 
40  $this->startForm();
41  $this->addModeOptions();
42  $this->addEmailOptions();
43  $this->addSkinOptions();
44  $this->addExtensionOptions();
45  $this->addFileOptions();
46  $this->addPersonalizationOptions();
47  $this->addAdvancedOptions();
48  $this->endForm();
49 
50  return null;
51  }
52 
53  private function addPersonalizationOptions() {
55  $this->addHTML(
56  $this->getFieldsetStart( 'config-personalization-settings' ) .
57  Html::rawElement( 'div', [
58  'class' => 'config-drag-drop'
59  ], wfMessage( 'config-logo-summary' )->parse() ) .
60  Html::openElement( 'div', [
61  'class' => 'config-personalization-options'
62  ] ) .
63  Html::hidden( 'config_LogoSiteName', $this->getVar( 'wgSitename' ) ) .
65  'var' => '_LogoIcon',
66  // Single quotes are intentional, LocalSettingsGenerator must output this unescaped.
67  'value' => '$wgResourceBasePath/resources/assets/change-your-logo.svg',
68  'label' => 'config-logo-icon',
69  'attribs' => [ 'dir' => 'ltr' ],
70  'help' => $parent->getHelpBox( 'config-logo-icon-help' )
71  ] ) .
73  'var' => '_LogoWordmark',
74  'label' => 'config-logo-wordmark',
75  'attribs' => [ 'dir' => 'ltr' ],
76  'help' => $parent->getHelpBox( 'config-logo-wordmark-help' )
77  ] ) .
79  'var' => '_LogoTagline',
80  'label' => 'config-logo-tagline',
81  'attribs' => [ 'dir' => 'ltr' ],
82  'help' => $parent->getHelpBox( 'config-logo-tagline-help' )
83  ] ) .
85  'var' => '_Logo1x',
86  'label' => 'config-logo-sidebar',
87  'attribs' => [ 'dir' => 'ltr' ],
88  'help' => $parent->getHelpBox( 'config-logo-sidebar-help' )
89  ] ) .
90  Html::openElement( 'div', [
91  'class' => 'logo-preview-area',
92  'data-main-page' => wfMessage( 'config-logo-preview-main' ),
93  'data-filedrop' => wfMessage( 'config-logo-filedrop' )
94  ] ) .
95  Html::closeElement( 'div' ) .
96  Html::closeElement( 'div' ) .
97  $this->getFieldsetEnd()
98  );
99  }
100 
105  private function addModeOptions(): void {
106  $this->addHTML(
107  # User Rights
108  // getRadioSet() builds a set of labeled radio buttons.
109  // For grep: The following messages are used as the item labels:
110  // config-profile-wiki, config-profile-no-anon, config-profile-fishbowl, config-profile-private
111  $this->parent->getRadioSet( [
112  'var' => '_RightsProfile',
113  'label' => 'config-profile',
114  'itemLabelPrefix' => 'config-profile-',
115  'values' => array_keys( $this->parent->rightsProfiles ),
116  ] ) .
117  $this->parent->getInfoBox( wfMessage( 'config-profile-help' )->plain() ) .
118 
119  # Licensing
120  // getRadioSet() builds a set of labeled radio buttons.
121  // For grep: The following messages are used as the item labels:
122  // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa,
123  // config-license-cc-0, config-license-pd, config-license-gfdl,
124  // config-license-none, config-license-cc-choose
125  $this->parent->getRadioSet( [
126  'var' => '_LicenseCode',
127  'label' => 'config-license',
128  'itemLabelPrefix' => 'config-license-',
129  'values' => array_keys( $this->parent->licenses ),
130  'commonAttribs' => [ 'class' => 'licenseRadio' ],
131  ] ) .
132  $this->getCCChooser() .
133  $this->parent->getHelpBox( 'config-license-help' )
134  );
135  }
136 
141  private function addEmailOptions(): void {
142  $emailwrapperStyle = $this->getVar( 'wgEnableEmail' ) ? '' : 'display: none';
143  $this->addHTML(
144  $this->getFieldsetStart( 'config-email-settings' ) .
145  $this->parent->getCheckBox( [
146  'var' => 'wgEnableEmail',
147  'label' => 'config-enable-email',
148  'attribs' => [ 'class' => 'showHideRadio', 'rel' => 'emailwrapper' ],
149  ] ) .
150  $this->parent->getHelpBox( 'config-enable-email-help' ) .
151  "<div id=\"emailwrapper\" style=\"$emailwrapperStyle\">" .
152  $this->parent->getTextBox( [
153  'var' => 'wgPasswordSender',
154  'label' => 'config-email-sender'
155  ] ) .
156  $this->parent->getHelpBox( 'config-email-sender-help' ) .
157  $this->parent->getCheckBox( [
158  'var' => 'wgEnableUserEmail',
159  'label' => 'config-email-user',
160  ] ) .
161  $this->parent->getHelpBox( 'config-email-user-help' ) .
162  $this->parent->getCheckBox( [
163  'var' => 'wgEnotifUserTalk',
164  'label' => 'config-email-usertalk',
165  ] ) .
166  $this->parent->getHelpBox( 'config-email-usertalk-help' ) .
167  $this->parent->getCheckBox( [
168  'var' => 'wgEnotifWatchlist',
169  'label' => 'config-email-watchlist',
170  ] ) .
171  $this->parent->getHelpBox( 'config-email-watchlist-help' ) .
172  $this->parent->getCheckBox( [
173  'var' => 'wgEmailAuthentication',
174  'label' => 'config-email-auth',
175  ] ) .
176  $this->parent->getHelpBox( 'config-email-auth-help' ) .
177  "</div>" .
178  $this->getFieldsetEnd()
179  );
180  }
181 
186  private function addSkinOptions(): void {
187  $skins = $this->parent->findExtensions( 'skins' )->value;
188  '@phan-var array[] $skins';
189  $skinHtml = $this->getFieldsetStart( 'config-skins' );
190 
191  $skinNames = array_map( 'strtolower', array_keys( $skins ) );
192  $chosenSkinName = $this->getVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) );
193 
194  if ( $skins ) {
195  $radioButtons = $this->parent->getRadioElements( [
196  'var' => 'wgDefaultSkin',
197  'itemLabels' => array_fill_keys( $skinNames, 'config-skins-use-as-default' ),
198  'values' => $skinNames,
199  'value' => $chosenSkinName,
200  ] );
201 
202  foreach ( $skins as $skin => $info ) {
203  if ( isset( $info['screenshots'] ) ) {
204  $screenshotText = $this->makeScreenshotsLink( $skin, $info['screenshots'] );
205  } else {
206  $screenshotText = htmlspecialchars( $skin );
207  }
208  $skinHtml .=
209  '<div class="config-skins-item">' .
210  $this->parent->getCheckBox( [
211  'var' => "skin-$skin",
212  'rawtext' => $screenshotText . $this->makeMoreInfoLink( $info ),
213  'value' => $this->getVar( "skin-$skin", true ), // all found skins enabled by default
214  ] ) .
215  '<div class="config-skins-use-as-default">' . $radioButtons[strtolower( $skin )] . '</div>' .
216  '</div>';
217  }
218  } else {
219  $skinHtml .=
220  Html::warningBox( wfMessage( 'config-skins-missing' )->plain(), 'config-warning-box' ) .
221  Html::hidden( 'config_wgDefaultSkin', $chosenSkinName );
222  }
223 
224  $skinHtml .= $this->parent->getHelpBox( 'config-skins-help' ) .
225  $this->getFieldsetEnd();
226  $this->addHTML( $skinHtml );
227  }
228 
233  private function addExtensionOptions(): void {
234  global $wgLang;
235 
236  $extensions = $this->parent->findExtensions()->value;
237  '@phan-var array[] $extensions';
238  $dependencyMap = [];
239 
240  if ( $extensions ) {
241  $extHtml = $this->getFieldsetStart( 'config-extensions' );
242 
243  $extByType = [];
244  $types = SpecialVersion::getExtensionTypes();
245  // Sort by type first
246  foreach ( $extensions as $ext => $info ) {
247  if ( !isset( $info['type'] ) || !isset( $types[$info['type']] ) ) {
248  // We let extensions normally define custom types, but
249  // since we aren't loading extensions, we'll have to
250  // categorize them under other
251  $info['type'] = 'other';
252  }
253  $extByType[$info['type']][$ext] = $info;
254  }
255 
256  foreach ( $types as $type => $message ) {
257  if ( !isset( $extByType[$type] ) ) {
258  continue;
259  }
260  $extHtml .= Html::element( 'h2', [], $message );
261  foreach ( $extByType[$type] as $ext => $info ) {
262  $attribs = [
263  'data-name' => $ext,
264  'class' => 'config-ext-input'
265  ];
266  $labelAttribs = [];
267  if ( isset( $info['requires']['extensions'] ) ) {
268  $dependencyMap[$ext]['extensions'] = $info['requires']['extensions'];
269  $labelAttribs['class'] = 'mw-ext-with-dependencies';
270  }
271  if ( isset( $info['requires']['skins'] ) ) {
272  $dependencyMap[$ext]['skins'] = $info['requires']['skins'];
273  $labelAttribs['class'] = 'mw-ext-with-dependencies';
274  }
275  if ( isset( $dependencyMap[$ext] ) ) {
276  $links = [];
277  // For each dependency, link to the checkbox for each
278  // extension/skin that is required
279  if ( isset( $dependencyMap[$ext]['extensions'] ) ) {
280  foreach ( $dependencyMap[$ext]['extensions'] as $name ) {
281  $links[] = Html::element(
282  'a',
283  [ 'href' => "#config_ext-$name" ],
284  $name
285  );
286  }
287  }
288  if ( isset( $dependencyMap[$ext]['skins'] ) ) {
289  // @phan-suppress-next-line PhanTypeMismatchForeach Phan internal bug
290  foreach ( $dependencyMap[$ext]['skins'] as $name ) {
291  $links[] = Html::element(
292  'a',
293  [ 'href' => "#config_skin-$name" ],
294  $name
295  );
296  }
297  }
298 
299  $text = wfMessage( 'config-extensions-requires' )
300  ->rawParams( $ext, $wgLang->commaList( $links ) )
301  ->escaped();
302  } else {
303  $text = $ext;
304  }
305  $extHtml .= $this->parent->getCheckBox( [
306  'var' => "ext-$ext",
307  'rawtext' => $text . $this->makeMoreInfoLink( $info ),
308  'attribs' => $attribs,
309  'labelAttribs' => $labelAttribs,
310  ] );
311  }
312  }
313 
314  $extHtml .= $this->parent->getHelpBox( 'config-extensions-help' ) .
315  $this->getFieldsetEnd();
316  $this->addHTML( $extHtml );
317  // Push the dependency map to the client side
318  $this->addHTML( Html::inlineScript(
319  'var extDependencyMap = ' . Html::encodeJsVar( $dependencyMap )
320  ) );
321  }
322  }
323 
328  private function addFileOptions(): void {
329  // Having / in paths in Windows looks funny :)
330  $this->setVar( 'wgDeletedDirectory',
331  str_replace(
332  '/', DIRECTORY_SEPARATOR,
333  $this->getVar( 'wgDeletedDirectory' )
334  )
335  );
336 
337  $uploadwrapperStyle = $this->getVar( 'wgEnableUploads' ) ? '' : 'display: none';
338  $this->addHTML(
339  # Uploading
340  $this->getFieldsetStart( 'config-upload-settings' ) .
341  $this->parent->getCheckBox( [
342  'var' => 'wgEnableUploads',
343  'label' => 'config-upload-enable',
344  'attribs' => [ 'class' => 'showHideRadio', 'rel' => 'uploadwrapper' ],
345  'help' => $this->parent->getHelpBox( 'config-upload-help' )
346  ] ) .
347  '<div id="uploadwrapper" style="' . $uploadwrapperStyle . '">' .
348  $this->parent->getTextBox( [
349  'var' => 'wgDeletedDirectory',
350  'label' => 'config-upload-deleted',
351  'attribs' => [ 'dir' => 'ltr' ],
352  'help' => $this->parent->getHelpBox( 'config-upload-deleted-help' )
353  ] ) .
354  '</div>'
355  );
356  $this->addHTML(
357  $this->parent->getCheckBox( [
358  'var' => 'wgUseInstantCommons',
359  'label' => 'config-instantcommons',
360  'help' => $this->parent->getHelpBox( 'config-instantcommons-help' )
361  ] ) .
362  $this->getFieldsetEnd()
363  );
364  }
365 
370  private function addAdvancedOptions(): void {
371  $caches = [ 'none' ];
372  $cachevalDefault = 'none';
373 
374  if ( count( $this->getVar( '_Caches' ) ) ) {
375  // A CACHE_ACCEL implementation is available
376  $caches[] = 'accel';
377  $cachevalDefault = 'accel';
378  }
379  $caches[] = 'memcached';
380 
381  // We'll hide/show this on demand when the value changes, see config.js.
382  $cacheval = $this->getVar( '_MainCacheType' );
383  if ( !$cacheval ) {
384  // We need to set a default here; but don't hardcode it
385  // or we lose it every time we reload the page for validation
386  // or going back!
387  $cacheval = $cachevalDefault;
388  }
389  $hidden = ( $cacheval == 'memcached' ) ? '' : 'display: none';
390  $this->addHTML(
391  # Advanced settings
392  $this->getFieldsetStart( 'config-advanced-settings' ) .
393  # Object cache settings
394  // getRadioSet() builds a set of labeled radio buttons.
395  // For grep: The following messages are used as the item labels:
396  // config-cache-none, config-cache-accel, config-cache-memcached
397  $this->parent->getRadioSet( [
398  'var' => '_MainCacheType',
399  'label' => 'config-cache-options',
400  'itemLabelPrefix' => 'config-cache-',
401  'values' => $caches,
402  'value' => $cacheval,
403  ] ) .
404  $this->parent->getHelpBox( 'config-cache-help' ) .
405  "<div id=\"config-memcachewrapper\" style=\"$hidden\">" .
406  $this->parent->getTextArea( [
407  'var' => '_MemCachedServers',
408  'label' => 'config-memcached-servers',
409  'help' => $this->parent->getHelpBox( 'config-memcached-help' )
410  ] ) .
411  '</div>' .
412  $this->getFieldsetEnd()
413  );
414  }
415 
421  private function makeScreenshotsLink( $name, $screenshots ) {
422  global $wgLang;
423  if ( count( $screenshots ) > 1 ) {
424  $links = [];
425  $counter = 1;
426 
427  foreach ( $screenshots as $shot ) {
428  $links[] = Html::element(
429  'a',
430  [ 'href' => $shot, 'target' => '_blank' ],
431  $wgLang->formatNum( $counter++ )
432  );
433  }
434  return wfMessage( 'config-skins-screenshots' )
435  ->rawParams( $name, $wgLang->commaList( $links ) )
436  ->escaped();
437  } else {
438  $link = Html::element(
439  'a',
440  [ 'href' => $screenshots[0], 'target' => '_blank' ],
441  wfMessage( 'config-screenshot' )->text()
442  );
443  return wfMessage( 'config-skins-screenshot', $name )->rawParams( $link )->escaped();
444  }
445  }
446 
451  private function makeMoreInfoLink( $info ) {
452  if ( !isset( $info['url'] ) ) {
453  return '';
454  }
455  return ' ' . wfMessage( 'parentheses' )->rawParams(
456  Html::element(
457  'a',
458  [ 'href' => $info['url'] ],
459  wfMessage( 'config-ext-skins-more-info' )->text()
460  )
461  )->escaped();
462  }
463 
467  public function getCCPartnerUrl() {
468  $server = $this->getVar( 'wgServer' );
469  $exitUrl = $server . $this->parent->getUrl( [
470  'page' => 'Options',
471  'SubmitCC' => 'indeed',
472  'config__LicenseCode' => 'cc',
473  'config_wgRightsUrl' => '[license_url]',
474  'config_wgRightsText' => '[license_name]',
475  'config_wgRightsIcon' => '[license_button]',
476  ] );
477  $styleUrl = $server . dirname( dirname( $this->parent->getUrl() ) ) .
478  '/mw-config/config-cc.css';
479  $iframeUrl = 'https://creativecommons.org/license/?' .
480  wfArrayToCgi( [
481  'partner' => 'MediaWiki',
482  'exit_url' => $exitUrl,
483  'lang' => $this->getVar( '_UserLang' ),
484  'stylesheet' => $styleUrl,
485  ] );
486 
487  return $iframeUrl;
488  }
489 
493  public function getCCChooser() {
494  $iframeAttribs = [
495  'class' => 'config-cc-iframe',
496  'name' => 'config-cc-iframe',
497  'id' => 'config-cc-iframe',
498  'frameborder' => 0,
499  'width' => '100%',
500  'height' => '100%',
501  ];
502  if ( $this->getVar( '_CCDone' ) ) {
503  $iframeAttribs['src'] = $this->parent->getUrl( [ 'ShowCC' => 'yes' ] );
504  } else {
505  $iframeAttribs['src'] = $this->getCCPartnerUrl();
506  }
507  $wrapperStyle = ( $this->getVar( '_LicenseCode' ) == 'cc-choose' ) ? '' : 'display: none';
508 
509  return "<div class=\"config-cc-wrapper\" id=\"config-cc-wrapper\" style=\"$wrapperStyle\">\n" .
510  Html::element( 'iframe', $iframeAttribs ) .
511  "</div>\n";
512  }
513 
517  public function getCCDoneBox() {
518  $js = "parent.document.getElementById('config-cc-wrapper').style.height = '$1';";
519  // If you change this height, also change it in config.css
520  $expandJs = str_replace( '$1', '54em', $js );
521  $reduceJs = str_replace( '$1', '70px', $js );
522 
523  return '<p>' .
524  Html::element( 'img', [ 'src' => $this->getVar( 'wgRightsIcon' ) ] ) .
525  "\u{00A0}\u{00A0}" .
526  htmlspecialchars( $this->getVar( 'wgRightsText' ) ) .
527  "</p>\n" .
528  "<p style=\"text-align: center;\">" .
529  Html::element( 'a',
530  [
531  'href' => $this->getCCPartnerUrl(),
532  'onclick' => $expandJs,
533  ],
534  wfMessage( 'config-cc-again' )->text()
535  ) .
536  "</p>\n" .
537  "<script>\n" .
538  # Reduce the wrapper div height
539  htmlspecialchars( $reduceJs ) .
540  "\n" .
541  "</script>\n";
542  }
543 
544  public function submitCC() {
545  $newValues = $this->parent->setVarsFromRequest(
546  [ 'wgRightsUrl', 'wgRightsText', 'wgRightsIcon' ] );
547  if ( count( $newValues ) != 3 ) {
548  $this->parent->showError( 'config-cc-error' );
549 
550  return;
551  }
552  $this->setVar( '_CCDone', true );
553  $this->addHTML( $this->getCCDoneBox() );
554  }
555 
562  public function submitSkins() {
563  $skins = array_keys( $this->parent->findExtensions( 'skins' )->value );
564  $this->parent->setVar( '_Skins', $skins );
565 
566  if ( $skins ) {
567  $skinNames = array_map( 'strtolower', $skins );
568  $this->parent->setVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) );
569  }
570 
571  return true;
572  }
573 
577  public function submit() {
578  $this->parent->setVarsFromRequest( [ '_RightsProfile', '_LicenseCode',
579  'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads',
580  '_Logo1x', '_LogoWordmark', '_LogoTagline', '_LogoIcon',
581  'wgEnableUserEmail', 'wgEnotifUserTalk', 'wgEnotifWatchlist',
582  'wgEmailAuthentication', '_MainCacheType', '_MemCachedServers',
583  'wgUseInstantCommons', 'wgDefaultSkin' ] );
584 
585  $retVal = true;
586 
587  if ( !array_key_exists( $this->getVar( '_RightsProfile' ), $this->parent->rightsProfiles ) ) {
588  $this->setVar( '_RightsProfile', array_key_first( $this->parent->rightsProfiles ) );
589  }
590 
591  $code = $this->getVar( '_LicenseCode' );
592  if ( $code == 'cc-choose' ) {
593  if ( !$this->getVar( '_CCDone' ) ) {
594  $this->parent->showError( 'config-cc-not-chosen' );
595  $retVal = false;
596  }
597  } elseif ( array_key_exists( $code, $this->parent->licenses ) ) {
598  // Messages:
599  // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa,
600  // config-license-cc-0, config-license-pd, config-license-gfdl, config-license-none,
601  // config-license-cc-choose
602  $entry = $this->parent->licenses[$code];
603  $this->setVar( 'wgRightsText',
604  $entry['text'] ?? wfMessage( 'config-license-' . $code )->text() );
605  $this->setVar( 'wgRightsUrl', $entry['url'] );
606  $this->setVar( 'wgRightsIcon', $entry['icon'] );
607  } else {
608  $this->setVar( 'wgRightsText', '' );
609  $this->setVar( 'wgRightsUrl', '' );
610  $this->setVar( 'wgRightsIcon', '' );
611  }
612 
613  $skinsAvailable = array_keys( $this->parent->findExtensions( 'skins' )->value );
614  $skinsToInstall = [];
615  foreach ( $skinsAvailable as $skin ) {
616  $this->parent->setVarsFromRequest( [ "skin-$skin" ] );
617  if ( $this->getVar( "skin-$skin" ) ) {
618  $skinsToInstall[] = $skin;
619  }
620  }
621  $this->parent->setVar( '_Skins', $skinsToInstall );
622 
623  if ( !$skinsToInstall && $skinsAvailable ) {
624  $this->parent->showError( 'config-skins-must-enable-some' );
625  $retVal = false;
626  }
627  $defaultSkin = $this->getVar( 'wgDefaultSkin' );
628  $skinsToInstallLowercase = array_map( 'strtolower', $skinsToInstall );
629  if ( $skinsToInstall && !in_array( $defaultSkin, $skinsToInstallLowercase ) ) {
630  $this->parent->showError( 'config-skins-must-enable-default' );
631  $retVal = false;
632  }
633 
634  $extsAvailable = array_keys( $this->parent->findExtensions()->value );
635  $extsToInstall = [];
636  foreach ( $extsAvailable as $ext ) {
637  $this->parent->setVarsFromRequest( [ "ext-$ext" ] );
638  if ( $this->getVar( "ext-$ext" ) ) {
639  $extsToInstall[] = $ext;
640  }
641  }
642  $this->parent->setVar( '_Extensions', $extsToInstall );
643 
644  if ( $this->getVar( '_MainCacheType' ) == 'memcached' ) {
645  $memcServers = explode( "\n", $this->getVar( '_MemCachedServers' ) );
646  // FIXME: explode() will always result in an array of at least one string, even on null (when
647  // the string will be empty and you'll get a PHP warning), so this has never worked?
648  // @phan-suppress-next-line PhanImpossibleCondition
649  if ( !$memcServers ) {
650  $this->parent->showError( 'config-memcache-needservers' );
651  $retVal = false;
652  }
653 
654  foreach ( $memcServers as $server ) {
655  $memcParts = explode( ":", $server, 2 );
656  if ( !isset( $memcParts[0] )
657  || ( !IPUtils::isValid( $memcParts[0] )
658  && ( gethostbyname( $memcParts[0] ) == $memcParts[0] ) )
659  ) {
660  $this->parent->showError( 'config-memcache-badip', $memcParts[0] );
661  $retVal = false;
662  } elseif ( !isset( $memcParts[1] ) ) {
663  $this->parent->showError( 'config-memcache-noport', $memcParts[0] );
664  $retVal = false;
665  } elseif ( $memcParts[1] < 1 || $memcParts[1] > 65535 ) {
666  $this->parent->showError( 'config-memcache-badport', 1, 65535 );
667  $retVal = false;
668  }
669  }
670  }
671 
672  return $retVal;
673  }
674 
675 }
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') &&! $wgCommandLineMode) $wgLang
Definition: Setup.php:535
This class is a collection of static functions that serve two purposes:
Definition: Html.php:57
Give information about the version of MediaWiki, PHP, the DB and extensions.
submitSkins()
If the user skips this installer page, we still need to set up the default skins, but ignore everythi...
Abstract class to define pages for the web installer.
WebInstaller $parent
The WebInstaller object this WebInstallerPage belongs to.
getFieldsetEnd()
Get the end tag of a fieldset.
endForm( $continue='continue', $back='back')
getVar( $var, $default=null)
getFieldsetStart( $legend)
Get the starting tags of a fieldset.
getTextBox( $params)
Get a labelled text box to configure a variable.
getHelpBox( $msg,... $args)
Get small text indented help for a preceding form field.
if(!is_readable( $file)) $ext
Definition: router.php:48