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