Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 358 |
|
0.00% |
0 / 12 |
CRAP | |
0.00% |
0 / 1 |
| WebInstallerOptions | |
0.00% |
0 / 358 |
|
0.00% |
0 / 12 |
3660 | |
0.00% |
0 / 1 |
| execute | |
0.00% |
0 / 15 |
|
0.00% |
0 / 1 |
20 | |||
| addPersonalizationOptions | |
0.00% |
0 / 44 |
|
0.00% |
0 / 1 |
2 | |||
| addModeOptions | |
0.00% |
0 / 17 |
|
0.00% |
0 / 1 |
2 | |||
| addEmailOptions | |
0.00% |
0 / 38 |
|
0.00% |
0 / 1 |
6 | |||
| addSkinOptions | |
0.00% |
0 / 30 |
|
0.00% |
0 / 1 |
20 | |||
| addExtensionOptions | |
0.00% |
0 / 59 |
|
0.00% |
0 / 1 |
240 | |||
| addFileOptions | |
0.00% |
0 / 32 |
|
0.00% |
0 / 1 |
6 | |||
| addAdvancedOptions | |
0.00% |
0 / 29 |
|
0.00% |
0 / 1 |
20 | |||
| makeScreenshotsLink | |
0.00% |
0 / 19 |
|
0.00% |
0 / 1 |
12 | |||
| makeMoreInfoLink | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
6 | |||
| submitSkins | |
0.00% |
0 / 6 |
|
0.00% |
0 / 1 |
6 | |||
| submit | |
0.00% |
0 / 60 |
|
0.00% |
0 / 1 |
420 | |||
| 1 | <?php |
| 2 | |
| 3 | /** |
| 4 | * @license GPL-2.0-or-later |
| 5 | * @file |
| 6 | * @ingroup Installer |
| 7 | */ |
| 8 | |
| 9 | namespace MediaWiki\Installer; |
| 10 | |
| 11 | use MediaWiki\Context\RequestContext; |
| 12 | use MediaWiki\Html\Html; |
| 13 | use MediaWiki\Specials\SpecialVersion; |
| 14 | use Wikimedia\IPUtils; |
| 15 | |
| 16 | class WebInstallerOptions extends WebInstallerPage { |
| 17 | |
| 18 | /** |
| 19 | * @return string|null |
| 20 | */ |
| 21 | public function execute() { |
| 22 | if ( $this->getVar( '_SkipOptional' ) == 'skip' ) { |
| 23 | $this->submitSkins(); |
| 24 | return 'skip'; |
| 25 | } |
| 26 | if ( $this->parent->request->wasPosted() && $this->submit() ) { |
| 27 | return 'continue'; |
| 28 | } |
| 29 | |
| 30 | $this->startForm(); |
| 31 | $this->addModeOptions(); |
| 32 | $this->addEmailOptions(); |
| 33 | $this->addSkinOptions(); |
| 34 | $this->addExtensionOptions(); |
| 35 | $this->addFileOptions(); |
| 36 | $this->addPersonalizationOptions(); |
| 37 | $this->addAdvancedOptions(); |
| 38 | $this->endForm(); |
| 39 | |
| 40 | return null; |
| 41 | } |
| 42 | |
| 43 | private function addPersonalizationOptions() { |
| 44 | $parent = $this->parent; |
| 45 | $this->addHTML( |
| 46 | $this->getFieldsetStart( 'config-personalization-settings' ) . |
| 47 | Html::rawElement( 'div', [ |
| 48 | 'class' => 'config-drag-drop' |
| 49 | ], wfMessage( 'config-logo-summary' )->parse() ) . |
| 50 | Html::openElement( 'div', [ |
| 51 | 'class' => 'config-personalization-options' |
| 52 | ] ) . |
| 53 | Html::hidden( 'config_LogoSiteName', $this->getVar( 'wgSitename' ) ) . |
| 54 | $parent->getTextBox( [ |
| 55 | 'var' => '_LogoIcon', |
| 56 | // Single quotes are intentional, LocalSettingsGenerator must output this unescaped. |
| 57 | 'value' => '$wgResourceBasePath/resources/assets/change-your-logo.svg', |
| 58 | 'label' => 'config-logo-icon', |
| 59 | 'attribs' => [ 'dir' => 'ltr' ], |
| 60 | 'help' => $parent->getHelpBox( 'config-logo-icon-help' ) |
| 61 | ] ) . |
| 62 | $parent->getTextBox( [ |
| 63 | 'var' => '_LogoWordmark', |
| 64 | 'label' => 'config-logo-wordmark', |
| 65 | 'attribs' => [ 'dir' => 'ltr' ], |
| 66 | 'help' => $parent->getHelpBox( 'config-logo-wordmark-help' ) |
| 67 | ] ) . |
| 68 | $parent->getTextBox( [ |
| 69 | 'var' => '_LogoTagline', |
| 70 | 'label' => 'config-logo-tagline', |
| 71 | 'attribs' => [ 'dir' => 'ltr' ], |
| 72 | 'help' => $parent->getHelpBox( 'config-logo-tagline-help' ) |
| 73 | ] ) . |
| 74 | $parent->getTextBox( [ |
| 75 | 'var' => '_Logo1x', |
| 76 | 'label' => 'config-logo-sidebar', |
| 77 | 'attribs' => [ 'dir' => 'ltr' ], |
| 78 | 'help' => $parent->getHelpBox( 'config-logo-sidebar-help' ) |
| 79 | ] ) . |
| 80 | Html::openElement( 'div', [ |
| 81 | 'class' => 'logo-preview-area', |
| 82 | 'data-main-page' => wfMessage( 'config-logo-preview-main' ), |
| 83 | 'data-filedrop' => wfMessage( 'config-logo-filedrop' ) |
| 84 | ] ) . |
| 85 | Html::closeElement( 'div' ) . |
| 86 | Html::closeElement( 'div' ) . |
| 87 | $this->getFieldsetEnd() |
| 88 | ); |
| 89 | } |
| 90 | |
| 91 | /** |
| 92 | * Wiki mode - user rights and copyright model. |
| 93 | */ |
| 94 | private function addModeOptions(): void { |
| 95 | $this->addHTML( |
| 96 | # User Rights |
| 97 | // getRadioSet() builds a set of labeled radio buttons. |
| 98 | // For grep: The following messages are used as the item labels: |
| 99 | // config-profile-wiki, config-profile-no-anon, config-profile-fishbowl, config-profile-private |
| 100 | $this->parent->getRadioSet( [ |
| 101 | 'var' => '_RightsProfile', |
| 102 | 'label' => 'config-profile', |
| 103 | 'itemLabelPrefix' => 'config-profile-', |
| 104 | 'values' => array_keys( $this->parent->rightsProfiles ), |
| 105 | ] ) . |
| 106 | $this->parent->getInfoBox( wfMessage( 'config-profile-help' )->plain() ) . |
| 107 | |
| 108 | # Licensing |
| 109 | // getRadioSet() builds a set of labeled radio buttons. |
| 110 | // For grep: The following messages are used as the item labels: |
| 111 | // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa, |
| 112 | // config-license-cc-0, config-license-pd, config-license-gfdl, |
| 113 | // config-license-none |
| 114 | $this->parent->getRadioSet( [ |
| 115 | 'var' => '_LicenseCode', |
| 116 | 'label' => 'config-license', |
| 117 | 'itemLabelPrefix' => 'config-license-', |
| 118 | 'values' => array_keys( $this->parent->licenses ), |
| 119 | 'commonAttribs' => [ 'class' => 'licenseRadio' ], |
| 120 | ] ) . |
| 121 | $this->parent->getHelpBox( 'config-license-help' ) |
| 122 | ); |
| 123 | } |
| 124 | |
| 125 | /** |
| 126 | * User email options. |
| 127 | */ |
| 128 | private function addEmailOptions(): void { |
| 129 | $emailwrapperStyle = $this->getVar( 'wgEnableEmail' ) ? '' : 'display: none'; |
| 130 | $this->addHTML( |
| 131 | $this->getFieldsetStart( 'config-email-settings' ) . |
| 132 | $this->parent->getCheckBox( [ |
| 133 | 'var' => 'wgEnableEmail', |
| 134 | 'label' => 'config-enable-email', |
| 135 | 'attribs' => [ 'class' => 'showHideRadio', 'rel' => 'emailwrapper' ], |
| 136 | ] ) . |
| 137 | $this->parent->getHelpBox( 'config-enable-email-help' ) . |
| 138 | "<div id=\"emailwrapper\" style=\"$emailwrapperStyle\">" . |
| 139 | $this->parent->getTextBox( [ |
| 140 | 'var' => 'wgPasswordSender', |
| 141 | 'label' => 'config-email-sender' |
| 142 | ] ) . |
| 143 | $this->parent->getHelpBox( 'config-email-sender-help' ) . |
| 144 | $this->parent->getCheckBox( [ |
| 145 | 'var' => 'wgEnableUserEmail', |
| 146 | 'label' => 'config-email-user', |
| 147 | ] ) . |
| 148 | $this->parent->getHelpBox( 'config-email-user-help' ) . |
| 149 | $this->parent->getCheckBox( [ |
| 150 | 'var' => 'wgEnotifUserTalk', |
| 151 | 'label' => 'config-email-usertalk', |
| 152 | ] ) . |
| 153 | $this->parent->getHelpBox( 'config-email-usertalk-help' ) . |
| 154 | $this->parent->getCheckBox( [ |
| 155 | 'var' => 'wgEnotifWatchlist', |
| 156 | 'label' => 'config-email-watchlist', |
| 157 | ] ) . |
| 158 | $this->parent->getHelpBox( 'config-email-watchlist-help' ) . |
| 159 | $this->parent->getCheckBox( [ |
| 160 | 'var' => 'wgEmailAuthentication', |
| 161 | 'label' => 'config-email-auth', |
| 162 | ] ) . |
| 163 | $this->parent->getHelpBox( 'config-email-auth-help' ) . |
| 164 | "</div>" . |
| 165 | $this->getFieldsetEnd() |
| 166 | ); |
| 167 | } |
| 168 | |
| 169 | /** |
| 170 | * Opt-in for bundled skins. |
| 171 | */ |
| 172 | private function addSkinOptions(): void { |
| 173 | $skins = $this->parent->findExtensions( 'skins' )->value; |
| 174 | '@phan-var array[] $skins'; |
| 175 | $skinHtml = $this->getFieldsetStart( 'config-skins' ); |
| 176 | |
| 177 | $skinNames = array_map( 'strtolower', array_keys( $skins ) ); |
| 178 | $chosenSkinName = $this->getVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) ); |
| 179 | |
| 180 | if ( $skins ) { |
| 181 | $radioButtons = $this->parent->getRadioElements( [ |
| 182 | 'var' => 'wgDefaultSkin', |
| 183 | 'itemLabels' => array_fill_keys( $skinNames, 'config-skins-use-as-default' ), |
| 184 | 'values' => $skinNames, |
| 185 | 'value' => $chosenSkinName, |
| 186 | ] ); |
| 187 | |
| 188 | foreach ( $skins as $skin => $info ) { |
| 189 | if ( isset( $info['screenshots'] ) ) { |
| 190 | $screenshotText = $this->makeScreenshotsLink( $skin, $info['screenshots'] ); |
| 191 | } else { |
| 192 | $screenshotText = htmlspecialchars( $skin ); |
| 193 | } |
| 194 | $skinHtml .= |
| 195 | '<div class="config-skins-item">' . |
| 196 | $this->parent->getCheckBox( [ |
| 197 | 'var' => "skin-$skin", |
| 198 | 'rawtext' => $screenshotText . $this->makeMoreInfoLink( $info ), |
| 199 | 'value' => $this->getVar( "skin-$skin", true ), // all found skins enabled by default |
| 200 | ] ) . |
| 201 | '<div class="config-skins-use-as-default">' . $radioButtons[strtolower( $skin )] . '</div>' . |
| 202 | '</div>'; |
| 203 | } |
| 204 | } else { |
| 205 | $skinHtml .= |
| 206 | Html::warningBox( wfMessage( 'config-skins-missing' )->parse(), 'config-warning-box' ) . |
| 207 | Html::hidden( 'config_wgDefaultSkin', $chosenSkinName ); |
| 208 | } |
| 209 | |
| 210 | $skinHtml .= $this->parent->getHelpBox( 'config-skins-help' ) . |
| 211 | $this->getFieldsetEnd(); |
| 212 | $this->addHTML( $skinHtml ); |
| 213 | } |
| 214 | |
| 215 | /** |
| 216 | * Opt-in for bundled extensions. |
| 217 | */ |
| 218 | private function addExtensionOptions(): void { |
| 219 | $lang = RequestContext::getMain()->getLanguage(); |
| 220 | |
| 221 | $extensions = $this->parent->findExtensions()->value; |
| 222 | '@phan-var array[] $extensions'; |
| 223 | $dependencyMap = []; |
| 224 | |
| 225 | if ( $extensions ) { |
| 226 | $extHtml = $this->getFieldsetStart( 'config-extensions' ); |
| 227 | |
| 228 | $extByType = []; |
| 229 | $types = SpecialVersion::getExtensionTypes(); |
| 230 | // Sort by type first |
| 231 | foreach ( $extensions as $ext => $info ) { |
| 232 | if ( !isset( $info['type'] ) || !isset( $types[$info['type']] ) ) { |
| 233 | // We let extensions normally define custom types, but |
| 234 | // since we aren't loading extensions, we'll have to |
| 235 | // categorize them under other |
| 236 | $info['type'] = 'other'; |
| 237 | } |
| 238 | $extByType[$info['type']][$ext] = $info; |
| 239 | } |
| 240 | |
| 241 | foreach ( $types as $type => $message ) { |
| 242 | if ( !isset( $extByType[$type] ) ) { |
| 243 | continue; |
| 244 | } |
| 245 | $extHtml .= Html::element( 'h2', [], $message ); |
| 246 | foreach ( $extByType[$type] as $ext => $info ) { |
| 247 | $attribs = [ |
| 248 | 'data-name' => $ext, |
| 249 | 'class' => 'config-ext-input cdx-checkbox__input' |
| 250 | ]; |
| 251 | $labelAttribs = []; |
| 252 | if ( isset( $info['requires']['extensions'] ) ) { |
| 253 | $dependencyMap[$ext]['extensions'] = $info['requires']['extensions']; |
| 254 | $labelAttribs['class'] = 'mw-ext-with-dependencies'; |
| 255 | } |
| 256 | if ( isset( $info['requires']['skins'] ) ) { |
| 257 | $dependencyMap[$ext]['skins'] = $info['requires']['skins']; |
| 258 | $labelAttribs['class'] = 'mw-ext-with-dependencies'; |
| 259 | } |
| 260 | if ( isset( $dependencyMap[$ext] ) ) { |
| 261 | $links = []; |
| 262 | // For each dependency, link to the checkbox for each |
| 263 | // extension/skin that is required |
| 264 | if ( isset( $dependencyMap[$ext]['extensions'] ) ) { |
| 265 | foreach ( $dependencyMap[$ext]['extensions'] as $name ) { |
| 266 | $links[] = Html::element( |
| 267 | 'a', |
| 268 | [ 'href' => "#config_ext-$name" ], |
| 269 | $name |
| 270 | ); |
| 271 | } |
| 272 | } |
| 273 | if ( isset( $dependencyMap[$ext]['skins'] ) ) { |
| 274 | // @phan-suppress-next-line PhanTypeMismatchForeach Phan internal bug |
| 275 | foreach ( $dependencyMap[$ext]['skins'] as $name ) { |
| 276 | $links[] = Html::element( |
| 277 | 'a', |
| 278 | [ 'href' => "#config_skin-$name" ], |
| 279 | $name |
| 280 | ); |
| 281 | } |
| 282 | } |
| 283 | |
| 284 | $text = wfMessage( 'config-extensions-requires', $ext ) |
| 285 | ->rawParams( $lang->commaList( $links ) ) |
| 286 | ->escaped(); |
| 287 | } else { |
| 288 | $text = htmlspecialchars( $ext ); |
| 289 | } |
| 290 | $extHtml .= $this->parent->getCheckBox( [ |
| 291 | 'var' => "ext-$ext", |
| 292 | 'rawtext' => $text . $this->makeMoreInfoLink( $info ), |
| 293 | 'attribs' => $attribs, |
| 294 | 'labelAttribs' => $labelAttribs, |
| 295 | ] ); |
| 296 | } |
| 297 | } |
| 298 | |
| 299 | $extHtml .= $this->parent->getHelpBox( 'config-extensions-help' ) . |
| 300 | $this->getFieldsetEnd(); |
| 301 | $this->addHTML( $extHtml ); |
| 302 | // Push the dependency map to the client side |
| 303 | $this->addHTML( $this->inlineScript( |
| 304 | 'var extDependencyMap = ' . Html::encodeJsVar( $dependencyMap ) |
| 305 | ) ); |
| 306 | } |
| 307 | } |
| 308 | |
| 309 | /** |
| 310 | * Image and file upload options. |
| 311 | */ |
| 312 | private function addFileOptions(): void { |
| 313 | // Having / in paths in Windows looks funny :) |
| 314 | $this->setVar( 'wgDeletedDirectory', |
| 315 | str_replace( |
| 316 | '/', DIRECTORY_SEPARATOR, |
| 317 | $this->getVar( 'wgDeletedDirectory' ) |
| 318 | ) |
| 319 | ); |
| 320 | |
| 321 | $uploadwrapperStyle = $this->getVar( 'wgEnableUploads' ) ? '' : 'display: none'; |
| 322 | $this->addHTML( |
| 323 | # Uploading |
| 324 | $this->getFieldsetStart( 'config-upload-settings' ) . |
| 325 | $this->parent->getCheckBox( [ |
| 326 | 'var' => 'wgEnableUploads', |
| 327 | 'label' => 'config-upload-enable', |
| 328 | 'attribs' => [ 'class' => 'showHideRadio', 'rel' => 'uploadwrapper' ], |
| 329 | 'help' => $this->parent->getHelpBox( 'config-upload-help' ) |
| 330 | ] ) . |
| 331 | '<div id="uploadwrapper" style="' . $uploadwrapperStyle . '">' . |
| 332 | $this->parent->getTextBox( [ |
| 333 | 'var' => 'wgDeletedDirectory', |
| 334 | 'label' => 'config-upload-deleted', |
| 335 | 'attribs' => [ 'dir' => 'ltr' ], |
| 336 | 'help' => $this->parent->getHelpBox( 'config-upload-deleted-help' ) |
| 337 | ] ) . |
| 338 | '</div>' |
| 339 | ); |
| 340 | $this->addHTML( |
| 341 | $this->parent->getCheckBox( [ |
| 342 | 'var' => 'wgUseInstantCommons', |
| 343 | 'label' => 'config-instantcommons', |
| 344 | 'help' => $this->parent->getHelpBox( 'config-instantcommons-help' ) |
| 345 | ] ) . |
| 346 | $this->getFieldsetEnd() |
| 347 | ); |
| 348 | } |
| 349 | |
| 350 | /** |
| 351 | * System administration related options. |
| 352 | */ |
| 353 | private function addAdvancedOptions(): void { |
| 354 | $caches = [ 'none' ]; |
| 355 | $cachevalDefault = 'none'; |
| 356 | |
| 357 | if ( count( $this->getVar( '_Caches' ) ) ) { |
| 358 | // A CACHE_ACCEL implementation is available |
| 359 | $caches[] = 'accel'; |
| 360 | $cachevalDefault = 'accel'; |
| 361 | } |
| 362 | $caches[] = 'memcached'; |
| 363 | |
| 364 | // We'll hide/show this on demand when the value changes, see config.js. |
| 365 | $cacheval = $this->getVar( '_MainCacheType' ); |
| 366 | if ( !$cacheval ) { |
| 367 | // We need to set a default here; but don't hardcode it |
| 368 | // or we lose it every time we reload the page for validation |
| 369 | // or going back! |
| 370 | $cacheval = $cachevalDefault; |
| 371 | } |
| 372 | $hidden = ( $cacheval == 'memcached' ) ? '' : 'display: none'; |
| 373 | $this->addHTML( |
| 374 | # Advanced settings |
| 375 | $this->getFieldsetStart( 'config-advanced-settings' ) . |
| 376 | # Object cache settings |
| 377 | // getRadioSet() builds a set of labeled radio buttons. |
| 378 | // For grep: The following messages are used as the item labels: |
| 379 | // config-cache-none, config-cache-accel, config-cache-memcached |
| 380 | $this->parent->getRadioSet( [ |
| 381 | 'var' => '_MainCacheType', |
| 382 | 'label' => 'config-cache-options', |
| 383 | 'itemLabelPrefix' => 'config-cache-', |
| 384 | 'values' => $caches, |
| 385 | 'value' => $cacheval, |
| 386 | ] ) . |
| 387 | $this->parent->getHelpBox( 'config-cache-help' ) . |
| 388 | "<div id=\"config-memcachewrapper\" style=\"$hidden\">" . |
| 389 | $this->parent->getTextArea( [ |
| 390 | 'var' => '_MemCachedServers', |
| 391 | 'label' => 'config-memcached-servers', |
| 392 | 'help' => $this->parent->getHelpBox( 'config-memcached-help' ) |
| 393 | ] ) . |
| 394 | '</div>' . |
| 395 | $this->getFieldsetEnd() |
| 396 | ); |
| 397 | } |
| 398 | |
| 399 | /** |
| 400 | * @param string $name |
| 401 | * @param array $screenshots |
| 402 | * @return string HTML |
| 403 | */ |
| 404 | private function makeScreenshotsLink( $name, $screenshots ) { |
| 405 | $lang = RequestContext::getMain()->getLanguage(); |
| 406 | if ( count( $screenshots ) > 1 ) { |
| 407 | $links = []; |
| 408 | $counter = 1; |
| 409 | |
| 410 | foreach ( $screenshots as $shot ) { |
| 411 | $links[] = Html::element( |
| 412 | 'a', |
| 413 | [ 'href' => $shot, 'target' => '_blank' ], |
| 414 | $lang->formatNum( $counter++ ) |
| 415 | ); |
| 416 | } |
| 417 | return wfMessage( 'config-skins-screenshots', $name ) |
| 418 | ->rawParams( $lang->commaList( $links ) ) |
| 419 | ->escaped(); |
| 420 | } else { |
| 421 | $link = Html::element( |
| 422 | 'a', |
| 423 | [ 'href' => $screenshots[0], 'target' => '_blank' ], |
| 424 | wfMessage( 'config-screenshot' )->text() |
| 425 | ); |
| 426 | return wfMessage( 'config-skins-screenshot', $name )->rawParams( $link )->escaped(); |
| 427 | } |
| 428 | } |
| 429 | |
| 430 | /** |
| 431 | * @param array $info |
| 432 | * @return string HTML |
| 433 | */ |
| 434 | private function makeMoreInfoLink( $info ) { |
| 435 | if ( !isset( $info['url'] ) ) { |
| 436 | return ''; |
| 437 | } |
| 438 | return ' ' . wfMessage( 'parentheses' )->rawParams( |
| 439 | Html::element( |
| 440 | 'a', |
| 441 | [ 'href' => $info['url'] ], |
| 442 | wfMessage( 'config-ext-skins-more-info' )->text() |
| 443 | ) |
| 444 | )->escaped(); |
| 445 | } |
| 446 | |
| 447 | /** |
| 448 | * If the user skips this installer page, we still need to set up the default skins, but ignore |
| 449 | * everything else. |
| 450 | * |
| 451 | * @return bool |
| 452 | */ |
| 453 | public function submitSkins() { |
| 454 | $skins = array_keys( $this->parent->findExtensions( 'skins' )->value ); |
| 455 | $this->parent->setVar( '_Skins', $skins ); |
| 456 | |
| 457 | if ( $skins ) { |
| 458 | $skinNames = array_map( 'strtolower', $skins ); |
| 459 | $this->parent->setVar( 'wgDefaultSkin', $this->parent->getDefaultSkin( $skinNames ) ); |
| 460 | } |
| 461 | |
| 462 | return true; |
| 463 | } |
| 464 | |
| 465 | /** |
| 466 | * @return bool |
| 467 | */ |
| 468 | public function submit() { |
| 469 | $this->parent->setVarsFromRequest( [ '_RightsProfile', '_LicenseCode', |
| 470 | 'wgEnableEmail', 'wgPasswordSender', 'wgEnableUploads', |
| 471 | '_Logo1x', '_LogoWordmark', '_LogoTagline', '_LogoIcon', |
| 472 | 'wgEnableUserEmail', 'wgEnotifUserTalk', 'wgEnotifWatchlist', |
| 473 | 'wgEmailAuthentication', '_MainCacheType', '_MemCachedServers', |
| 474 | 'wgUseInstantCommons', 'wgDefaultSkin' ] ); |
| 475 | |
| 476 | $retVal = true; |
| 477 | |
| 478 | if ( !array_key_exists( $this->getVar( '_RightsProfile' ), $this->parent->rightsProfiles ) ) { |
| 479 | $this->setVar( '_RightsProfile', array_key_first( $this->parent->rightsProfiles ) ); |
| 480 | } |
| 481 | |
| 482 | $code = $this->getVar( '_LicenseCode' ); |
| 483 | if ( array_key_exists( $code, $this->parent->licenses ) ) { |
| 484 | // Messages: |
| 485 | // config-license-cc-by, config-license-cc-by-sa, config-license-cc-by-nc-sa, |
| 486 | // config-license-cc-0, config-license-pd, config-license-gfdl, config-license-none |
| 487 | $entry = $this->parent->licenses[$code]; |
| 488 | $this->setVar( 'wgRightsText', |
| 489 | $entry['text'] ?? wfMessage( 'config-license-' . $code )->text() ); |
| 490 | $this->setVar( 'wgRightsUrl', $entry['url'] ); |
| 491 | $this->setVar( 'wgRightsIcon', $entry['icon'] ); |
| 492 | } else { |
| 493 | $this->setVar( 'wgRightsText', '' ); |
| 494 | $this->setVar( 'wgRightsUrl', '' ); |
| 495 | $this->setVar( 'wgRightsIcon', '' ); |
| 496 | } |
| 497 | |
| 498 | $skinsAvailable = array_keys( $this->parent->findExtensions( 'skins' )->value ); |
| 499 | $skinsToInstall = []; |
| 500 | foreach ( $skinsAvailable as $skin ) { |
| 501 | $this->parent->setVarsFromRequest( [ "skin-$skin" ] ); |
| 502 | if ( $this->getVar( "skin-$skin" ) ) { |
| 503 | $skinsToInstall[] = $skin; |
| 504 | } |
| 505 | } |
| 506 | $this->parent->setVar( '_Skins', $skinsToInstall ); |
| 507 | |
| 508 | if ( !$skinsToInstall && $skinsAvailable ) { |
| 509 | $this->parent->showError( 'config-skins-must-enable-some' ); |
| 510 | $retVal = false; |
| 511 | } |
| 512 | $defaultSkin = $this->getVar( 'wgDefaultSkin' ); |
| 513 | $skinsToInstallLowercase = array_map( 'strtolower', $skinsToInstall ); |
| 514 | if ( $skinsToInstall && !in_array( $defaultSkin, $skinsToInstallLowercase ) ) { |
| 515 | $this->parent->showError( 'config-skins-must-enable-default' ); |
| 516 | $retVal = false; |
| 517 | } |
| 518 | |
| 519 | $extsAvailable = array_keys( $this->parent->findExtensions()->value ); |
| 520 | $extsToInstall = []; |
| 521 | foreach ( $extsAvailable as $ext ) { |
| 522 | $this->parent->setVarsFromRequest( [ "ext-$ext" ] ); |
| 523 | if ( $this->getVar( "ext-$ext" ) ) { |
| 524 | $extsToInstall[] = $ext; |
| 525 | } |
| 526 | } |
| 527 | $this->parent->setVar( '_Extensions', $extsToInstall ); |
| 528 | |
| 529 | if ( $this->getVar( '_MainCacheType' ) == 'memcached' ) { |
| 530 | $memcServers = explode( "\n", $this->getVar( '_MemCachedServers' ) ); |
| 531 | // FIXME: explode() will always result in an array of at least one string, even on null (when |
| 532 | // the string will be empty and you'll get a PHP warning), so this has never worked? |
| 533 | // @phan-suppress-next-line PhanImpossibleCondition |
| 534 | if ( !$memcServers ) { |
| 535 | $this->parent->showError( 'config-memcache-needservers' ); |
| 536 | $retVal = false; |
| 537 | } |
| 538 | |
| 539 | foreach ( $memcServers as $server ) { |
| 540 | $memcParts = explode( ":", $server, 2 ); |
| 541 | if ( !isset( $memcParts[0] ) |
| 542 | || ( !IPUtils::isValid( $memcParts[0] ) |
| 543 | && ( gethostbyname( $memcParts[0] ) == $memcParts[0] ) ) |
| 544 | ) { |
| 545 | $this->parent->showError( 'config-memcache-badip', $memcParts[0] ); |
| 546 | $retVal = false; |
| 547 | } elseif ( !isset( $memcParts[1] ) ) { |
| 548 | $this->parent->showError( 'config-memcache-noport', $memcParts[0] ); |
| 549 | $retVal = false; |
| 550 | } elseif ( $memcParts[1] < 1 || $memcParts[1] > 65535 ) { |
| 551 | $this->parent->showError( 'config-memcache-badport', 1, 65535 ); |
| 552 | $retVal = false; |
| 553 | } |
| 554 | } |
| 555 | } |
| 556 | |
| 557 | return $retVal; |
| 558 | } |
| 559 | |
| 560 | } |