MediaWiki  master
WebInstallerOptions.php
Go to the documentation of this file.
1 <?php
22 use Wikimedia\IPUtils;
23 
25 
29  public function execute() {
30  global $wgLang;
31 
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  $emailwrapperStyle = $this->getVar( 'wgEnableEmail' ) ? '' : 'display: none';
41  $this->startForm();
42  $this->addHTML(
43  # User Rights
44  // getRadioSet() builds a set of labeled radio buttons.
45  // For grep: The following messages are used as the item labels:
46  // config-profile-wiki, config-profile-no-anon, config-profile-fishbowl, config-profile-private
47  $this->parent->getRadioSet( [
48  'var' => '_RightsProfile',
49  'label' => 'config-profile',
50  'itemLabelPrefix' => 'config-profile-',
51  'values' => array_keys( $this->parent->rightsProfiles ),
52  ] ) .
53  $this->parent->getInfoBox( wfMessage( 'config-profile-help' )->plain() ) .
54 
55  # Licensing
56  // getRadioSet() builds a set of labeled radio buttons.
57  // For grep: The following messages are used as the item labels:
58  // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa,
59  // config-license-cc-0, config-license-pd, config-license-gfdl,
60  // config-license-none, config-license-cc-choose
61  $this->parent->getRadioSet( [
62  'var' => '_LicenseCode',
63  'label' => 'config-license',
64  'itemLabelPrefix' => 'config-license-',
65  'values' => array_keys( $this->parent->licenses ),
66  'commonAttribs' => [ 'class' => 'licenseRadio' ],
67  ] ) .
68  $this->getCCChooser() .
69  $this->parent->getHelpBox( 'config-license-help' ) .
70 
71  # E-mail
72  $this->getFieldsetStart( 'config-email-settings' ) .
73  $this->parent->getCheckBox( [
74  'var' => 'wgEnableEmail',
75  'label' => 'config-enable-email',
76  'attribs' => [ 'class' => 'showHideRadio', 'rel' => 'emailwrapper' ],
77  ] ) .
78  $this->parent->getHelpBox( 'config-enable-email-help' ) .
79  "<div id=\"emailwrapper\" style=\"$emailwrapperStyle\">" .
80  $this->parent->getTextBox( [
81  'var' => 'wgPasswordSender',
82  'label' => 'config-email-sender'
83  ] ) .
84  $this->parent->getHelpBox( 'config-email-sender-help' ) .
85  $this->parent->getCheckBox( [
86  'var' => 'wgEnableUserEmail',
87  'label' => 'config-email-user',
88  ] ) .
89  $this->parent->getHelpBox( 'config-email-user-help' ) .
90  $this->parent->getCheckBox( [
91  'var' => 'wgEnotifUserTalk',
92  'label' => 'config-email-usertalk',
93  ] ) .
94  $this->parent->getHelpBox( 'config-email-usertalk-help' ) .
95  $this->parent->getCheckBox( [
96  'var' => 'wgEnotifWatchlist',
97  'label' => 'config-email-watchlist',
98  ] ) .
99  $this->parent->getHelpBox( 'config-email-watchlist-help' ) .
100  $this->parent->getCheckBox( [
101  'var' => 'wgEmailAuthentication',
102  'label' => 'config-email-auth',
103  ] ) .
104  $this->parent->getHelpBox( 'config-email-auth-help' ) .
105  "</div>" .
106  $this->getFieldsetEnd()
107  );
108 
109  $skins = $this->parent->findExtensions( 'skins' )->value;
110  '@phan-var array[] $skins';
111  $skinHtml = $this->getFieldsetStart( 'config-skins' );
112 
113  $skinNames = array_map( 'strtolower', array_keys( $skins ) );
114  $chosenSkinName = $this->getVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) );
115 
116  if ( $skins ) {
117  $radioButtons = $this->parent->getRadioElements( [
118  'var' => 'wgDefaultSkin',
119  'itemLabels' => array_fill_keys( $skinNames, 'config-skins-use-as-default' ),
120  'values' => $skinNames,
121  'value' => $chosenSkinName,
122  ] );
123 
124  foreach ( $skins as $skin => $info ) {
125  if ( isset( $info['screenshots'] ) ) {
126  $screenshotText = $this->makeScreenshotsLink( $skin, $info['screenshots'] );
127  } else {
128  $screenshotText = htmlspecialchars( $skin );
129  }
130  $skinHtml .=
131  '<div class="config-skins-item">' .
132  $this->parent->getCheckBox( [
133  'var' => "skin-$skin",
134  'rawtext' => $screenshotText,
135  'value' => $this->getVar( "skin-$skin", true ), // all found skins enabled by default
136  ] ) .
137  '<div class="config-skins-use-as-default">' . $radioButtons[strtolower( $skin )] . '</div>' .
138  '</div>';
139  }
140  } else {
141  $skinHtml .=
142  Html::warningBox( wfMessage( 'config-skins-missing' )->plain(), 'config-warning-box' ) .
143  Html::hidden( 'config_wgDefaultSkin', $chosenSkinName );
144  }
145 
146  $skinHtml .= $this->parent->getHelpBox( 'config-skins-help' ) .
147  $this->getFieldsetEnd();
148  $this->addHTML( $skinHtml );
149 
150  $extensions = $this->parent->findExtensions()->value;
151  '@phan-var array[] $extensions';
152  $dependencyMap = [];
153 
154  if ( $extensions ) {
155  $extHtml = $this->getFieldsetStart( 'config-extensions' );
156 
157  $extByType = [];
159  // Sort by type first
160  foreach ( $extensions as $ext => $info ) {
161  if ( !isset( $info['type'] ) || !isset( $types[$info['type']] ) ) {
162  // We let extensions normally define custom types, but
163  // since we aren't loading extensions, we'll have to
164  // categorize them under other
165  $info['type'] = 'other';
166  }
167  $extByType[$info['type']][$ext] = $info;
168  }
169 
170  foreach ( $types as $type => $message ) {
171  if ( !isset( $extByType[$type] ) ) {
172  continue;
173  }
174  $extHtml .= Html::element( 'h2', [], $message );
175  foreach ( $extByType[$type] as $ext => $info ) {
176  $urlText = '';
177  if ( isset( $info['url'] ) ) {
178  $urlText = ' ' . Html::element( 'a', [ 'href' => $info['url'] ], '(more information)' );
179  }
180  $attribs = [
181  'data-name' => $ext,
182  'class' => 'config-ext-input'
183  ];
184  $labelAttribs = [];
185  $fullDepList = [];
186  if ( isset( $info['requires']['extensions'] ) ) {
187  $dependencyMap[$ext]['extensions'] = $info['requires']['extensions'];
188  $labelAttribs['class'] = 'mw-ext-with-dependencies';
189  }
190  if ( isset( $info['requires']['skins'] ) ) {
191  $dependencyMap[$ext]['skins'] = $info['requires']['skins'];
192  $labelAttribs['class'] = 'mw-ext-with-dependencies';
193  }
194  if ( isset( $dependencyMap[$ext] ) ) {
195  $links = [];
196  // For each dependency, link to the checkbox for each
197  // extension/skin that is required
198  if ( isset( $dependencyMap[$ext]['extensions'] ) ) {
199  foreach ( $dependencyMap[$ext]['extensions'] as $name ) {
200  $links[] = Html::element(
201  'a',
202  [ 'href' => "#config_ext-$name" ],
203  $name
204  );
205  }
206  }
207  if ( isset( $dependencyMap[$ext]['skins'] ) ) {
208  // @phan-suppress-next-line PhanTypeMismatchForeach Phan internal bug
209  foreach ( $dependencyMap[$ext]['skins'] as $name ) {
210  $links[] = Html::element(
211  'a',
212  [ 'href' => "#config_skin-$name" ],
213  $name
214  );
215  }
216  }
217 
218  // @phan-suppress-next-line SecurityCheck-XSS
219  $text = wfMessage( 'config-extensions-requires' )
220  ->rawParams( $ext, $wgLang->commaList( $links ) )
221  ->escaped();
222  } else {
223  $text = $ext;
224  }
225  $extHtml .= $this->parent->getCheckBox( [
226  'var' => "ext-$ext",
227  'rawtext' => $text,
228  'attribs' => $attribs,
229  'labelAttribs' => $labelAttribs,
230  ] );
231  }
232  }
233 
234  $extHtml .= $this->parent->getHelpBox( 'config-extensions-help' ) .
235  $this->getFieldsetEnd();
236  $this->addHTML( $extHtml );
237  // Push the dependency map to the client side
238  $this->addHTML( Html::inlineScript(
239  'var extDependencyMap = ' . Xml::encodeJsVar( $dependencyMap )
240  ) );
241  }
242 
243  // Having / in paths in Windows looks funny :)
244  $this->setVar( 'wgDeletedDirectory',
245  str_replace(
246  '/', DIRECTORY_SEPARATOR,
247  $this->getVar( 'wgDeletedDirectory' )
248  )
249  );
250 
251  $uploadwrapperStyle = $this->getVar( 'wgEnableUploads' ) ? '' : 'display: none';
252  $this->addHTML(
253  # Uploading
254  $this->getFieldsetStart( 'config-upload-settings' ) .
255  $this->parent->getCheckBox( [
256  'var' => 'wgEnableUploads',
257  'label' => 'config-upload-enable',
258  'attribs' => [ 'class' => 'showHideRadio', 'rel' => 'uploadwrapper' ],
259  'help' => $this->parent->getHelpBox( 'config-upload-help' )
260  ] ) .
261  '<div id="uploadwrapper" style="' . $uploadwrapperStyle . '">' .
262  $this->parent->getTextBox( [
263  'var' => 'wgDeletedDirectory',
264  'label' => 'config-upload-deleted',
265  'attribs' => [ 'dir' => 'ltr' ],
266  'help' => $this->parent->getHelpBox( 'config-upload-deleted-help' )
267  ] ) .
268  '</div>' .
269  $this->parent->getTextBox( [
270  'var' => '_Logo',
271  'label' => 'config-logo',
272  'attribs' => [ 'dir' => 'ltr' ],
273  'help' => $this->parent->getHelpBox( 'config-logo-help' )
274  ] )
275  );
276  $this->addHTML(
277  $this->parent->getCheckBox( [
278  'var' => 'wgUseInstantCommons',
279  'label' => 'config-instantcommons',
280  'help' => $this->parent->getHelpBox( 'config-instantcommons-help' )
281  ] ) .
282  $this->getFieldsetEnd()
283  );
284 
285  $caches = [ 'none' ];
286  $cachevalDefault = 'none';
287 
288  if ( count( $this->getVar( '_Caches' ) ) ) {
289  // A CACHE_ACCEL implementation is available
290  $caches[] = 'accel';
291  $cachevalDefault = 'accel';
292  }
293  $caches[] = 'memcached';
294 
295  // We'll hide/show this on demand when the value changes, see config.js.
296  $cacheval = $this->getVar( '_MainCacheType' );
297  if ( !$cacheval ) {
298  // We need to set a default here; but don't hardcode it
299  // or we lose it every time we reload the page for validation
300  // or going back!
301  $cacheval = $cachevalDefault;
302  }
303  $hidden = ( $cacheval == 'memcached' ) ? '' : 'display: none';
304  $this->addHTML(
305  # Advanced settings
306  $this->getFieldsetStart( 'config-advanced-settings' ) .
307  # Object cache settings
308  // getRadioSet() builds a set of labeled radio buttons.
309  // For grep: The following messages are used as the item labels:
310  // config-cache-none, config-cache-accel, config-cache-memcached
311  $this->parent->getRadioSet( [
312  'var' => '_MainCacheType',
313  'label' => 'config-cache-options',
314  'itemLabelPrefix' => 'config-cache-',
315  'values' => $caches,
316  'value' => $cacheval,
317  ] ) .
318  $this->parent->getHelpBox( 'config-cache-help' ) .
319  "<div id=\"config-memcachewrapper\" style=\"$hidden\">" .
320  $this->parent->getTextArea( [
321  'var' => '_MemCachedServers',
322  'label' => 'config-memcached-servers',
323  'help' => $this->parent->getHelpBox( 'config-memcached-help' )
324  ] ) .
325  '</div>' .
326  $this->getFieldsetEnd()
327  );
328  $this->endForm();
329 
330  return null;
331  }
332 
338  private function makeScreenshotsLink( $name, $screenshots ) {
339  global $wgLang;
340  if ( count( $screenshots ) > 1 ) {
341  $links = [];
342  $counter = 1;
343 
344  foreach ( $screenshots as $shot ) {
345  $links[] = Html::element(
346  'a',
347  [ 'href' => $shot, 'target' => '_blank' ],
348  $wgLang->formatNum( $counter++ )
349  );
350  }
351  return wfMessage( 'config-skins-screenshots' )
352  ->rawParams( $name, $wgLang->commaList( $links ) )
353  ->escaped();
354  } else {
355  $link = Html::element(
356  'a',
357  [ 'href' => $screenshots[0], 'target' => '_blank' ],
358  wfMessage( 'config-screenshot' )->text()
359  );
360  return wfMessage( 'config-skins-screenshot', $name )->rawParams( $link )->escaped();
361  }
362  }
363 
367  public function getCCPartnerUrl() {
368  $server = $this->getVar( 'wgServer' );
369  $exitUrl = $server . $this->parent->getUrl( [
370  'page' => 'Options',
371  'SubmitCC' => 'indeed',
372  'config__LicenseCode' => 'cc',
373  'config_wgRightsUrl' => '[license_url]',
374  'config_wgRightsText' => '[license_name]',
375  'config_wgRightsIcon' => '[license_button]',
376  ] );
377  $styleUrl = $server . dirname( dirname( $this->parent->getUrl() ) ) .
378  '/mw-config/config-cc.css';
379  $iframeUrl = 'https://creativecommons.org/license/?' .
380  wfArrayToCgi( [
381  'partner' => 'MediaWiki',
382  'exit_url' => $exitUrl,
383  'lang' => $this->getVar( '_UserLang' ),
384  'stylesheet' => $styleUrl,
385  ] );
386 
387  return $iframeUrl;
388  }
389 
393  public function getCCChooser() {
394  $iframeAttribs = [
395  'class' => 'config-cc-iframe',
396  'name' => 'config-cc-iframe',
397  'id' => 'config-cc-iframe',
398  'frameborder' => 0,
399  'width' => '100%',
400  'height' => '100%',
401  ];
402  if ( $this->getVar( '_CCDone' ) ) {
403  $iframeAttribs['src'] = $this->parent->getUrl( [ 'ShowCC' => 'yes' ] );
404  } else {
405  $iframeAttribs['src'] = $this->getCCPartnerUrl();
406  }
407  $wrapperStyle = ( $this->getVar( '_LicenseCode' ) == 'cc-choose' ) ? '' : 'display: none';
408 
409  return "<div class=\"config-cc-wrapper\" id=\"config-cc-wrapper\" style=\"$wrapperStyle\">\n" .
410  Html::element( 'iframe', $iframeAttribs ) .
411  "</div>\n";
412  }
413 
417  public function getCCDoneBox() {
418  $js = "parent.document.getElementById('config-cc-wrapper').style.height = '$1';";
419  // If you change this height, also change it in config.css
420  $expandJs = str_replace( '$1', '54em', $js );
421  $reduceJs = str_replace( '$1', '70px', $js );
422 
423  return '<p>' .
424  Html::element( 'img', [ 'src' => $this->getVar( 'wgRightsIcon' ) ] ) .
425  "\u{00A0}\u{00A0}" .
426  htmlspecialchars( $this->getVar( 'wgRightsText' ) ) .
427  "</p>\n" .
428  "<p style=\"text-align: center;\">" .
429  Html::element( 'a',
430  [
431  'href' => $this->getCCPartnerUrl(),
432  'onclick' => $expandJs,
433  ],
434  wfMessage( 'config-cc-again' )->text()
435  ) .
436  "</p>\n" .
437  "<script>\n" .
438  # Reduce the wrapper div height
439  htmlspecialchars( $reduceJs ) .
440  "\n" .
441  "</script>\n";
442  }
443 
444  public function submitCC() {
445  $newValues = $this->parent->setVarsFromRequest(
446  [ 'wgRightsUrl', 'wgRightsText', 'wgRightsIcon' ] );
447  if ( count( $newValues ) != 3 ) {
448  $this->parent->showError( 'config-cc-error' );
449 
450  return;
451  }
452  $this->setVar( '_CCDone', true );
453  $this->addHTML( $this->getCCDoneBox() );
454  }
455 
462  public function submitSkins() {
463  $skins = array_keys( $this->parent->findExtensions( 'skins' )->value );
464  $this->parent->setVar( '_Skins', $skins );
465 
466  if ( $skins ) {
467  $skinNames = array_map( 'strtolower', $skins );
468  $this->parent->setVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) );
469  }
470 
471  return true;
472  }
473 
477  public function submit() {
478  $this->parent->setVarsFromRequest( [ '_RightsProfile', '_LicenseCode',
479  'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads', '_Logo',
480  'wgEnableUserEmail', 'wgEnotifUserTalk', 'wgEnotifWatchlist',
481  'wgEmailAuthentication', '_MainCacheType', '_MemCachedServers',
482  'wgUseInstantCommons', 'wgDefaultSkin' ] );
483 
484  $retVal = true;
485 
486  if ( !array_key_exists( $this->getVar( '_RightsProfile' ), $this->parent->rightsProfiles ) ) {
487  reset( $this->parent->rightsProfiles );
488  $this->setVar( '_RightsProfile', key( $this->parent->rightsProfiles ) );
489  }
490 
491  // If this is empty, either the default got lost internally
492  // or the user blanked it
493  if ( strval( $this->getVar( '_Logo' ) ) === '' ) {
494  $this->parent->showError( 'config-install-logo-blank' );
495  $retVal = false;
496  }
497 
498  $code = $this->getVar( '_LicenseCode' );
499  if ( $code == 'cc-choose' ) {
500  if ( !$this->getVar( '_CCDone' ) ) {
501  $this->parent->showError( 'config-cc-not-chosen' );
502  $retVal = false;
503  }
504  } elseif ( array_key_exists( $code, $this->parent->licenses ) ) {
505  // Messages:
506  // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa,
507  // config-license-cc-0, config-license-pd, config-license-gfdl, config-license-none,
508  // config-license-cc-choose
509  $entry = $this->parent->licenses[$code];
510  $this->setVar( 'wgRightsText',
511  $entry['text'] ?? wfMessage( 'config-license-' . $code )->text() );
512  $this->setVar( 'wgRightsUrl', $entry['url'] );
513  $this->setVar( 'wgRightsIcon', $entry['icon'] );
514  } else {
515  $this->setVar( 'wgRightsText', '' );
516  $this->setVar( 'wgRightsUrl', '' );
517  $this->setVar( 'wgRightsIcon', '' );
518  }
519 
520  $skinsAvailable = array_keys( $this->parent->findExtensions( 'skins' )->value );
521  $skinsToInstall = [];
522  foreach ( $skinsAvailable as $skin ) {
523  $this->parent->setVarsFromRequest( [ "skin-$skin" ] );
524  if ( $this->getVar( "skin-$skin" ) ) {
525  $skinsToInstall[] = $skin;
526  }
527  }
528  $this->parent->setVar( '_Skins', $skinsToInstall );
529 
530  if ( !$skinsToInstall && $skinsAvailable ) {
531  $this->parent->showError( 'config-skins-must-enable-some' );
532  $retVal = false;
533  }
534  $defaultSkin = $this->getVar( 'wgDefaultSkin' );
535  $skinsToInstallLowercase = array_map( 'strtolower', $skinsToInstall );
536  if ( $skinsToInstall && array_search( $defaultSkin, $skinsToInstallLowercase ) === false ) {
537  $this->parent->showError( 'config-skins-must-enable-default' );
538  $retVal = false;
539  }
540 
541  $extsAvailable = array_keys( $this->parent->findExtensions()->value );
542  $extsToInstall = [];
543  foreach ( $extsAvailable as $ext ) {
544  $this->parent->setVarsFromRequest( [ "ext-$ext" ] );
545  if ( $this->getVar( "ext-$ext" ) ) {
546  $extsToInstall[] = $ext;
547  }
548  }
549  $this->parent->setVar( '_Extensions', $extsToInstall );
550 
551  if ( $this->getVar( '_MainCacheType' ) == 'memcached' ) {
552  $memcServers = explode( "\n", $this->getVar( '_MemCachedServers' ) );
553  if ( !$memcServers ) {
554  $this->parent->showError( 'config-memcache-needservers' );
555  $retVal = false;
556  }
557 
558  foreach ( $memcServers as $server ) {
559  $memcParts = explode( ":", $server, 2 );
560  if ( !isset( $memcParts[0] )
561  || ( !IPUtils::isValid( $memcParts[0] )
562  && ( gethostbyname( $memcParts[0] ) == $memcParts[0] ) )
563  ) {
564  $this->parent->showError( 'config-memcache-badip', $memcParts[0] );
565  $retVal = false;
566  } elseif ( !isset( $memcParts[1] ) ) {
567  $this->parent->showError( 'config-memcache-noport', $memcParts[0] );
568  $retVal = false;
569  } elseif ( $memcParts[1] < 1 || $memcParts[1] > 65535 ) {
570  $this->parent->showError( 'config-memcache-badport', 1, 65535 );
571  $retVal = false;
572  }
573  }
574  }
575 
576  return $retVal;
577  }
578 
579 }
WebInstallerPage\startForm
startForm()
Definition: WebInstallerPage.php:69
WebInstallerOptions\getCCChooser
getCCChooser()
Definition: WebInstallerOptions.php:393
WebInstallerPage\getFieldsetStart
getFieldsetStart( $legend)
Get the starting tags of a fieldset.
Definition: WebInstallerPage.php:171
WebInstallerOptions\getCCDoneBox
getCCDoneBox()
Definition: WebInstallerOptions.php:417
wfMessage
wfMessage( $key,... $params)
This is the function for getting translated interface messages.
Definition: GlobalFunctions.php:1175
Html\warningBox
static warningBox( $html, $className='')
Return a warning box.
Definition: Html.php:755
$wgLang
$wgLang
Definition: Setup.php:834
Xml\encodeJsVar
static encodeJsVar( $value, $pretty=false)
Encode a variable of arbitrary type to JavaScript.
Definition: Xml.php:673
WebInstallerPage\endForm
endForm( $continue='continue', $back='back')
Definition: WebInstallerPage.php:86
WebInstallerOptions\submit
submit()
Definition: WebInstallerOptions.php:477
WebInstallerPage\getVar
getVar( $var, $default=null)
Definition: WebInstallerPage.php:152
SpecialVersion\getExtensionTypes
static getExtensionTypes()
Returns an array with the base extension types.
Definition: SpecialVersion.php:415
WebInstallerPage\getFieldsetEnd
getFieldsetEnd()
Get the end tag of a fieldset.
Definition: WebInstallerPage.php:180
WebInstallerOptions\getCCPartnerUrl
getCCPartnerUrl()
Definition: WebInstallerOptions.php:367
WebInstallerOptions\execute
execute()
Definition: WebInstallerOptions.php:29
Html\hidden
static hidden( $name, $value, array $attribs=[])
Convenience function to produce an input element with type=hidden.
Definition: Html.php:831
WebInstallerOptions\makeScreenshotsLink
makeScreenshotsLink( $name, $screenshots)
Definition: WebInstallerOptions.php:338
Html\inlineScript
static inlineScript( $contents, $nonce=null)
Output an HTML script tag with the given contents.
Definition: Html.php:589
WebInstallerPage\addHTML
addHTML( $html)
Definition: WebInstallerPage.php:65
WebInstallerPage\setVar
setVar( $name, $value)
Definition: WebInstallerPage.php:160
WebInstallerPage
Abstract class to define pages for the web installer.
Definition: WebInstallerPage.php:30
WebInstallerOptions\submitCC
submitCC()
Definition: WebInstallerOptions.php:444
WebInstallerOptions\submitSkins
submitSkins()
If the user skips this installer page, we still need to set up the default skins, but ignore everythi...
Definition: WebInstallerOptions.php:462
$ext
if(!is_readable( $file)) $ext
Definition: router.php:48
Html\element
static element( $element, $attribs=[], $contents='')
Identical to rawElement(), but HTML-escapes $contents (like Xml::element()).
Definition: Html.php:232
User
The User object encapsulates all of the user-specific settings (user_id, name, rights,...
Definition: User.php:68
WebInstallerOptions
Definition: WebInstallerOptions.php:24
wfArrayToCgi
wfArrayToCgi( $array1, $array2=null, $prefix='')
This function takes one or two arrays as input, and returns a CGI-style string, e....
Definition: GlobalFunctions.php:330
$type
$type
Definition: testCompression.php:52