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