MediaWiki
REL1_20
|
00001 <?php 00048 class Preferences { 00049 static $defaultPreferences = null; 00050 static $saveFilters = array( 00051 'timecorrection' => array( 'Preferences', 'filterTimezoneInput' ), 00052 'cols' => array( 'Preferences', 'filterIntval' ), 00053 'rows' => array( 'Preferences', 'filterIntval' ), 00054 'rclimit' => array( 'Preferences', 'filterIntval' ), 00055 'wllimit' => array( 'Preferences', 'filterIntval' ), 00056 'searchlimit' => array( 'Preferences', 'filterIntval' ), 00057 ); 00058 00065 static function getPreferences( $user, IContextSource $context ) { 00066 if ( self::$defaultPreferences ) { 00067 return self::$defaultPreferences; 00068 } 00069 00070 $defaultPreferences = array(); 00071 00072 self::profilePreferences( $user, $context, $defaultPreferences ); 00073 self::skinPreferences( $user, $context, $defaultPreferences ); 00074 self::filesPreferences( $user, $context, $defaultPreferences ); 00075 self::datetimePreferences( $user, $context, $defaultPreferences ); 00076 self::renderingPreferences( $user, $context, $defaultPreferences ); 00077 self::editingPreferences( $user, $context, $defaultPreferences ); 00078 self::rcPreferences( $user, $context, $defaultPreferences ); 00079 self::watchlistPreferences( $user, $context, $defaultPreferences ); 00080 self::searchPreferences( $user, $context, $defaultPreferences ); 00081 self::miscPreferences( $user, $context, $defaultPreferences ); 00082 00083 wfRunHooks( 'GetPreferences', array( $user, &$defaultPreferences ) ); 00084 00085 ## Remove preferences that wikis don't want to use 00086 global $wgHiddenPrefs; 00087 foreach ( $wgHiddenPrefs as $pref ) { 00088 if ( isset( $defaultPreferences[$pref] ) ) { 00089 unset( $defaultPreferences[$pref] ); 00090 } 00091 } 00092 00093 ## Prod in defaults from the user 00094 foreach ( $defaultPreferences as $name => &$info ) { 00095 $prefFromUser = self::getOptionFromUser( $name, $info, $user ); 00096 $field = HTMLForm::loadInputFromParameters( $name, $info ); // For validation 00097 $defaultOptions = User::getDefaultOptions(); 00098 $globalDefault = isset( $defaultOptions[$name] ) 00099 ? $defaultOptions[$name] 00100 : null; 00101 00102 // If it validates, set it as the default 00103 if ( isset( $info['default'] ) ) { 00104 // Already set, no problem 00105 continue; 00106 } elseif ( !is_null( $prefFromUser ) && // Make sure we're not just pulling nothing 00107 $field->validate( $prefFromUser, $user->getOptions() ) === true ) { 00108 $info['default'] = $prefFromUser; 00109 } elseif ( $field->validate( $globalDefault, $user->getOptions() ) === true ) { 00110 $info['default'] = $globalDefault; 00111 } else { 00112 throw new MWException( "Global default '$globalDefault' is invalid for field $name" ); 00113 } 00114 } 00115 00116 self::$defaultPreferences = $defaultPreferences; 00117 00118 return $defaultPreferences; 00119 } 00120 00129 static function getOptionFromUser( $name, $info, $user ) { 00130 $val = $user->getOption( $name ); 00131 00132 // Handling for array-type preferences 00133 if ( ( isset( $info['type'] ) && $info['type'] == 'multiselect' ) || 00134 ( isset( $info['class'] ) && $info['class'] == 'HTMLMultiSelectField' ) ) { 00135 $options = HTMLFormField::flattenOptions( $info['options'] ); 00136 $prefix = isset( $info['prefix'] ) ? $info['prefix'] : $name; 00137 $val = array(); 00138 00139 foreach ( $options as $value ) { 00140 if ( $user->getOption( "$prefix$value" ) ) { 00141 $val[] = $value; 00142 } 00143 } 00144 } 00145 00146 return $val; 00147 } 00148 00155 static function profilePreferences( $user, IContextSource $context, &$defaultPreferences ) { 00156 global $wgAuth, $wgContLang, $wgParser, $wgCookieExpiration, $wgLanguageCode, 00157 $wgDisableTitleConversion, $wgDisableLangConversion, $wgMaxSigChars, 00158 $wgEnableEmail, $wgEmailConfirmToEdit, $wgEnableUserEmail, $wgEmailAuthentication, 00159 $wgEnotifWatchlist, $wgEnotifUserTalk, $wgEnotifRevealEditorAddress; 00160 00161 ## User info ##################################### 00162 // Information panel 00163 $defaultPreferences['username'] = array( 00164 'type' => 'info', 00165 'label-message' => 'username', 00166 'default' => $user->getName(), 00167 'section' => 'personal/info', 00168 ); 00169 00170 $defaultPreferences['userid'] = array( 00171 'type' => 'info', 00172 'label-message' => 'uid', 00173 'default' => $user->getId(), 00174 'section' => 'personal/info', 00175 ); 00176 00177 # Get groups to which the user belongs 00178 $userEffectiveGroups = $user->getEffectiveGroups(); 00179 $userGroups = $userMembers = array(); 00180 foreach ( $userEffectiveGroups as $ueg ) { 00181 if ( $ueg == '*' ) { 00182 // Skip the default * group, seems useless here 00183 continue; 00184 } 00185 $groupName = User::getGroupName( $ueg ); 00186 $userGroups[] = User::makeGroupLinkHTML( $ueg, $groupName ); 00187 00188 $memberName = User::getGroupMember( $ueg, $user->getName() ); 00189 $userMembers[] = User::makeGroupLinkHTML( $ueg, $memberName ); 00190 } 00191 asort( $userGroups ); 00192 asort( $userMembers ); 00193 00194 $lang = $context->getLanguage(); 00195 00196 $defaultPreferences['usergroups'] = array( 00197 'type' => 'info', 00198 'label' => $context->msg( 'prefs-memberingroups' )->numParams( 00199 count( $userGroups ) )->parse(), 00200 'default' => $context->msg( 'prefs-memberingroups-type', 00201 $lang->commaList( $userGroups ), 00202 $lang->commaList( $userMembers ) 00203 )->plain(), 00204 'raw' => true, 00205 'section' => 'personal/info', 00206 ); 00207 00208 $defaultPreferences['editcount'] = array( 00209 'type' => 'info', 00210 'label-message' => 'prefs-edits', 00211 'default' => $lang->formatNum( $user->getEditCount() ), 00212 'section' => 'personal/info', 00213 ); 00214 00215 if ( $user->getRegistration() ) { 00216 $displayUser = $context->getUser(); 00217 $userRegistration = $user->getRegistration(); 00218 $defaultPreferences['registrationdate'] = array( 00219 'type' => 'info', 00220 'label-message' => 'prefs-registration', 00221 'default' => $context->msg( 00222 'prefs-registration-date-time', 00223 $lang->userTimeAndDate( $userRegistration, $displayUser ), 00224 $lang->userDate( $userRegistration, $displayUser ), 00225 $lang->userTime( $userRegistration, $displayUser ) 00226 )->parse(), 00227 'section' => 'personal/info', 00228 ); 00229 } 00230 00231 // Actually changeable stuff 00232 $defaultPreferences['realname'] = array( 00233 'type' => $wgAuth->allowPropChange( 'realname' ) ? 'text' : 'info', 00234 'default' => $user->getRealName(), 00235 'section' => 'personal/info', 00236 'label-message' => 'yourrealname', 00237 'help-message' => 'prefs-help-realname', 00238 ); 00239 00240 $defaultPreferences['gender'] = array( 00241 'type' => 'select', 00242 'section' => 'personal/info', 00243 'options' => array( 00244 $context->msg( 'gender-male' )->text() => 'male', 00245 $context->msg( 'gender-female' )->text() => 'female', 00246 $context->msg( 'gender-unknown' )->text() => 'unknown', 00247 ), 00248 'label-message' => 'yourgender', 00249 'help-message' => 'prefs-help-gender', 00250 ); 00251 00252 if ( $wgAuth->allowPasswordChange() ) { 00253 $link = Linker::link( SpecialPage::getTitleFor( 'ChangePassword' ), 00254 $context->msg( 'prefs-resetpass' )->escaped(), array(), 00255 array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' ) ) ); 00256 00257 $defaultPreferences['password'] = array( 00258 'type' => 'info', 00259 'raw' => true, 00260 'default' => $link, 00261 'label-message' => 'yourpassword', 00262 'section' => 'personal/info', 00263 ); 00264 } 00265 if ( $wgCookieExpiration > 0 ) { 00266 $defaultPreferences['rememberpassword'] = array( 00267 'type' => 'toggle', 00268 'label' => $context->msg( 'tog-rememberpassword' )->numParams( 00269 ceil( $wgCookieExpiration / ( 3600 * 24 ) ) )->text(), 00270 'section' => 'personal/info', 00271 ); 00272 } 00273 00274 // Language 00275 $languages = Language::fetchLanguageNames( null, 'mw' ); 00276 if ( !array_key_exists( $wgLanguageCode, $languages ) ) { 00277 $languages[$wgLanguageCode] = $wgLanguageCode; 00278 } 00279 ksort( $languages ); 00280 00281 $options = array(); 00282 foreach ( $languages as $code => $name ) { 00283 $display = wfBCP47( $code ) . ' - ' . $name; 00284 $options[$display] = $code; 00285 } 00286 $defaultPreferences['language'] = array( 00287 'type' => 'select', 00288 'section' => 'personal/i18n', 00289 'options' => $options, 00290 'label-message' => 'yourlanguage', 00291 ); 00292 00293 /* see if there are multiple language variants to choose from*/ 00294 $variantArray = array(); 00295 if ( !$wgDisableLangConversion ) { 00296 $variants = $wgContLang->getVariants(); 00297 00298 foreach ( $variants as $v ) { 00299 $v = str_replace( '_', '-', strtolower( $v ) ); 00300 $variantArray[$v] = $wgContLang->getVariantname( $v, false ); 00301 } 00302 00303 $options = array(); 00304 foreach ( $variantArray as $code => $name ) { 00305 $display = wfBCP47( $code ) . ' - ' . $name; 00306 $options[$display] = $code; 00307 } 00308 00309 if ( count( $variantArray ) > 1 ) { 00310 $defaultPreferences['variant'] = array( 00311 'label-message' => 'yourvariant', 00312 'type' => 'select', 00313 'options' => $options, 00314 'section' => 'personal/i18n', 00315 'help-message' => 'prefs-help-variant', 00316 ); 00317 } 00318 } 00319 00320 if ( count( $variantArray ) > 1 && !$wgDisableLangConversion && !$wgDisableTitleConversion ) { 00321 $defaultPreferences['noconvertlink'] = 00322 array( 00323 'type' => 'toggle', 00324 'section' => 'personal/i18n', 00325 'label-message' => 'tog-noconvertlink', 00326 ); 00327 } 00328 00329 // show a preview of the old signature first 00330 $oldsigWikiText = $wgParser->preSaveTransform( "~~~", $context->getTitle(), $user, ParserOptions::newFromContext( $context ) ); 00331 $oldsigHTML = $context->getOutput()->parseInline( $oldsigWikiText, true, true ); 00332 $defaultPreferences['oldsig'] = array( 00333 'type' => 'info', 00334 'raw' => true, 00335 'label-message' => 'tog-oldsig', 00336 'default' => $oldsigHTML, 00337 'section' => 'personal/signature', 00338 ); 00339 $defaultPreferences['nickname'] = array( 00340 'type' => $wgAuth->allowPropChange( 'nickname' ) ? 'text' : 'info', 00341 'maxlength' => $wgMaxSigChars, 00342 'label-message' => 'yournick', 00343 'validation-callback' => array( 'Preferences', 'validateSignature' ), 00344 'section' => 'personal/signature', 00345 'filter-callback' => array( 'Preferences', 'cleanSignature' ), 00346 ); 00347 $defaultPreferences['fancysig'] = array( 00348 'type' => 'toggle', 00349 'label-message' => 'tog-fancysig', 00350 'help-message' => 'prefs-help-signature', // show general help about signature at the bottom of the section 00351 'section' => 'personal/signature' 00352 ); 00353 00354 ## Email stuff 00355 00356 if ( $wgEnableEmail ) { 00357 $helpMessages[] = $wgEmailConfirmToEdit 00358 ? 'prefs-help-email-required' 00359 : 'prefs-help-email' ; 00360 00361 if( $wgEnableUserEmail ) { 00362 // additional messages when users can send email to each other 00363 $helpMessages[] = 'prefs-help-email-others'; 00364 } 00365 00366 $link = Linker::link( 00367 SpecialPage::getTitleFor( 'ChangeEmail' ), 00368 $context->msg( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->escaped(), 00369 array(), 00370 array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' ) ) ); 00371 00372 $emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : ''; 00373 if ( $wgAuth->allowPropChange( 'emailaddress' ) ) { 00374 $emailAddress .= $emailAddress == '' ? $link : ( 00375 $context->msg( 'word-separator' )->plain() 00376 . $context->msg( 'parentheses' )->rawParams( $link )->plain() 00377 ); 00378 } 00379 00380 00381 $defaultPreferences['emailaddress'] = array( 00382 'type' => 'info', 00383 'raw' => true, 00384 'default' => $emailAddress, 00385 'label-message' => 'youremail', 00386 'section' => 'personal/email', 00387 'help-messages' => $helpMessages, 00388 # 'cssclass' chosen below 00389 ); 00390 00391 $disableEmailPrefs = false; 00392 00393 $emailauthenticationclass = 'mw-email-not-authenticated'; 00394 if ( $wgEmailAuthentication ) { 00395 if ( $user->getEmail() ) { 00396 if ( $user->getEmailAuthenticationTimestamp() ) { 00397 // date and time are separate parameters to facilitate localisation. 00398 // $time is kept for backward compat reasons. 00399 // 'emailauthenticated' is also used in SpecialConfirmemail.php 00400 $displayUser = $context->getUser(); 00401 $emailTimestamp = $user->getEmailAuthenticationTimestamp(); 00402 $time = $lang->userTimeAndDate( $emailTimestamp, $displayUser ); 00403 $d = $lang->userDate( $emailTimestamp, $displayUser ); 00404 $t = $lang->userTime( $emailTimestamp, $displayUser ); 00405 $emailauthenticated = $context->msg( 'emailauthenticated', 00406 $time, $d, $t )->parse() . '<br />'; 00407 $disableEmailPrefs = false; 00408 $emailauthenticationclass = 'mw-email-authenticated'; 00409 } else { 00410 $disableEmailPrefs = true; 00411 $emailauthenticated = $context->msg( 'emailnotauthenticated' )->parse() . '<br />' . 00412 Linker::linkKnown( 00413 SpecialPage::getTitleFor( 'Confirmemail' ), 00414 $context->msg( 'emailconfirmlink' )->escaped() 00415 ) . '<br />'; 00416 $emailauthenticationclass="mw-email-not-authenticated"; 00417 } 00418 } else { 00419 $disableEmailPrefs = true; 00420 $emailauthenticated = $context->msg( 'noemailprefs' )->escaped(); 00421 $emailauthenticationclass = 'mw-email-none'; 00422 } 00423 00424 $defaultPreferences['emailauthentication'] = array( 00425 'type' => 'info', 00426 'raw' => true, 00427 'section' => 'personal/email', 00428 'label-message' => 'prefs-emailconfirm-label', 00429 'default' => $emailauthenticated, 00430 # Apply the same CSS class used on the input to the message: 00431 'cssclass' => $emailauthenticationclass, 00432 ); 00433 } 00434 $defaultPreferences['emailaddress']['cssclass'] = $emailauthenticationclass; 00435 00436 if ( $wgEnableUserEmail && $user->isAllowed( 'sendemail' ) ) { 00437 $defaultPreferences['disablemail'] = array( 00438 'type' => 'toggle', 00439 'invert' => true, 00440 'section' => 'personal/email', 00441 'label-message' => 'allowemail', 00442 'disabled' => $disableEmailPrefs, 00443 ); 00444 $defaultPreferences['ccmeonemails'] = array( 00445 'type' => 'toggle', 00446 'section' => 'personal/email', 00447 'label-message' => 'tog-ccmeonemails', 00448 'disabled' => $disableEmailPrefs, 00449 ); 00450 } 00451 00452 if ( $wgEnotifWatchlist ) { 00453 $defaultPreferences['enotifwatchlistpages'] = array( 00454 'type' => 'toggle', 00455 'section' => 'personal/email', 00456 'label-message' => 'tog-enotifwatchlistpages', 00457 'disabled' => $disableEmailPrefs, 00458 ); 00459 } 00460 if ( $wgEnotifUserTalk ) { 00461 $defaultPreferences['enotifusertalkpages'] = array( 00462 'type' => 'toggle', 00463 'section' => 'personal/email', 00464 'label-message' => 'tog-enotifusertalkpages', 00465 'disabled' => $disableEmailPrefs, 00466 ); 00467 } 00468 if ( $wgEnotifUserTalk || $wgEnotifWatchlist ) { 00469 $defaultPreferences['enotifminoredits'] = array( 00470 'type' => 'toggle', 00471 'section' => 'personal/email', 00472 'label-message' => 'tog-enotifminoredits', 00473 'disabled' => $disableEmailPrefs, 00474 ); 00475 00476 if ( $wgEnotifRevealEditorAddress ) { 00477 $defaultPreferences['enotifrevealaddr'] = array( 00478 'type' => 'toggle', 00479 'section' => 'personal/email', 00480 'label-message' => 'tog-enotifrevealaddr', 00481 'disabled' => $disableEmailPrefs, 00482 ); 00483 } 00484 } 00485 } 00486 } 00487 00494 static function skinPreferences( $user, IContextSource $context, &$defaultPreferences ) { 00495 ## Skin ##################################### 00496 global $wgAllowUserCss, $wgAllowUserJs; 00497 00498 $defaultPreferences['skin'] = array( 00499 'type' => 'radio', 00500 'options' => self::generateSkinOptions( $user, $context ), 00501 'label' => ' ', 00502 'section' => 'rendering/skin', 00503 ); 00504 00505 # Create links to user CSS/JS pages for all skins 00506 # This code is basically copied from generateSkinOptions(). It'd 00507 # be nice to somehow merge this back in there to avoid redundancy. 00508 if ( $wgAllowUserCss || $wgAllowUserJs ) { 00509 $linkTools = array(); 00510 00511 if ( $wgAllowUserCss ) { 00512 $cssPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/common.css' ); 00513 $linkTools[] = Linker::link( $cssPage, $context->msg( 'prefs-custom-css' )->escaped() ); 00514 } 00515 00516 if ( $wgAllowUserJs ) { 00517 $jsPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/common.js' ); 00518 $linkTools[] = Linker::link( $jsPage, $context->msg( 'prefs-custom-js' )->escaped() ); 00519 } 00520 00521 $defaultPreferences['commoncssjs'] = array( 00522 'type' => 'info', 00523 'raw' => true, 00524 'default' => $context->getLanguage()->pipeList( $linkTools ), 00525 'label-message' => 'prefs-common-css-js', 00526 'section' => 'rendering/skin', 00527 ); 00528 } 00529 00530 $selectedSkin = $user->getOption( 'skin' ); 00531 if ( in_array( $selectedSkin, array( 'cologneblue', 'standard' ) ) ) { 00532 $settings = array_flip( $context->getLanguage()->getQuickbarSettings() ); 00533 00534 $defaultPreferences['quickbar'] = array( 00535 'type' => 'radio', 00536 'options' => $settings, 00537 'section' => 'rendering/skin', 00538 'label-message' => 'qbsettings', 00539 ); 00540 } 00541 } 00542 00548 static function filesPreferences( $user, IContextSource $context, &$defaultPreferences ) { 00549 ## Files ##################################### 00550 $defaultPreferences['imagesize'] = array( 00551 'type' => 'select', 00552 'options' => self::getImageSizes( $context ), 00553 'label-message' => 'imagemaxsize', 00554 'section' => 'rendering/files', 00555 ); 00556 $defaultPreferences['thumbsize'] = array( 00557 'type' => 'select', 00558 'options' => self::getThumbSizes( $context ), 00559 'label-message' => 'thumbsize', 00560 'section' => 'rendering/files', 00561 ); 00562 } 00563 00570 static function datetimePreferences( $user, IContextSource $context, &$defaultPreferences ) { 00571 ## Date and time ##################################### 00572 $dateOptions = self::getDateOptions( $context ); 00573 if ( $dateOptions ) { 00574 $defaultPreferences['date'] = array( 00575 'type' => 'radio', 00576 'options' => $dateOptions, 00577 'label' => ' ', 00578 'section' => 'datetime/dateformat', 00579 ); 00580 } 00581 00582 // Info 00583 $now = wfTimestampNow(); 00584 $lang = $context->getLanguage(); 00585 $nowlocal = Xml::element( 'span', array( 'id' => 'wpLocalTime' ), 00586 $lang->time( $now, true ) ); 00587 $nowserver = $lang->time( $now, false ) . 00588 Html::hidden( 'wpServerTime', (int)substr( $now, 8, 2 ) * 60 + (int)substr( $now, 10, 2 ) ); 00589 00590 $defaultPreferences['nowserver'] = array( 00591 'type' => 'info', 00592 'raw' => 1, 00593 'label-message' => 'servertime', 00594 'default' => $nowserver, 00595 'section' => 'datetime/timeoffset', 00596 ); 00597 00598 $defaultPreferences['nowlocal'] = array( 00599 'type' => 'info', 00600 'raw' => 1, 00601 'label-message' => 'localtime', 00602 'default' => $nowlocal, 00603 'section' => 'datetime/timeoffset', 00604 ); 00605 00606 // Grab existing pref. 00607 $tzOffset = $user->getOption( 'timecorrection' ); 00608 $tz = explode( '|', $tzOffset, 3 ); 00609 00610 $tzOptions = self::getTimezoneOptions( $context ); 00611 00612 $tzSetting = $tzOffset; 00613 if ( count( $tz ) > 1 && $tz[0] == 'Offset' ) { 00614 $minDiff = $tz[1]; 00615 $tzSetting = sprintf( '%+03d:%02d', floor( $minDiff / 60 ), abs( $minDiff ) % 60 ); 00616 } elseif ( count( $tz ) > 1 && $tz[0] == 'ZoneInfo' && 00617 !in_array( $tzOffset, HTMLFormField::flattenOptions( $tzOptions ) ) ) 00618 { 00619 # Timezone offset can vary with DST 00620 $userTZ = timezone_open( $tz[2] ); 00621 if ( $userTZ !== false ) { 00622 $minDiff = floor( timezone_offset_get( $userTZ, date_create( 'now' ) ) / 60 ); 00623 $tzSetting = "ZoneInfo|$minDiff|{$tz[2]}"; 00624 } 00625 } 00626 00627 $defaultPreferences['timecorrection'] = array( 00628 'class' => 'HTMLSelectOrOtherField', 00629 'label-message' => 'timezonelegend', 00630 'options' => $tzOptions, 00631 'default' => $tzSetting, 00632 'size' => 20, 00633 'section' => 'datetime/timeoffset', 00634 ); 00635 } 00636 00642 static function renderingPreferences( $user, IContextSource $context, &$defaultPreferences ) { 00643 ## Page Rendering ############################## 00644 global $wgAllowUserCssPrefs; 00645 if ( $wgAllowUserCssPrefs ) { 00646 $defaultPreferences['underline'] = array( 00647 'type' => 'select', 00648 'options' => array( 00649 $context->msg( 'underline-never' )->text() => 0, 00650 $context->msg( 'underline-always' )->text() => 1, 00651 $context->msg( 'underline-default' )->text() => 2, 00652 ), 00653 'label-message' => 'tog-underline', 00654 'section' => 'rendering/advancedrendering', 00655 ); 00656 } 00657 00658 $stubThresholdValues = array( 50, 100, 500, 1000, 2000, 5000, 10000 ); 00659 $stubThresholdOptions = array( $context->msg( 'stub-threshold-disabled' )->text() => 0 ); 00660 foreach ( $stubThresholdValues as $value ) { 00661 $stubThresholdOptions[$context->msg( 'size-bytes', $value )->text()] = $value; 00662 } 00663 00664 $defaultPreferences['stubthreshold'] = array( 00665 'type' => 'selectorother', 00666 'section' => 'rendering/advancedrendering', 00667 'options' => $stubThresholdOptions, 00668 'size' => 20, 00669 'label' => $context->msg( 'stub-threshold' )->text(), // Raw HTML message. Yay? 00670 ); 00671 00672 if ( $wgAllowUserCssPrefs ) { 00673 $defaultPreferences['showtoc'] = array( 00674 'type' => 'toggle', 00675 'section' => 'rendering/advancedrendering', 00676 'label-message' => 'tog-showtoc', 00677 ); 00678 } 00679 $defaultPreferences['nocache'] = array( 00680 'type' => 'toggle', 00681 'label-message' => 'tog-nocache', 00682 'section' => 'rendering/advancedrendering', 00683 ); 00684 $defaultPreferences['showhiddencats'] = array( 00685 'type' => 'toggle', 00686 'section' => 'rendering/advancedrendering', 00687 'label-message' => 'tog-showhiddencats' 00688 ); 00689 $defaultPreferences['showjumplinks'] = array( 00690 'type' => 'toggle', 00691 'section' => 'rendering/advancedrendering', 00692 'label-message' => 'tog-showjumplinks', 00693 ); 00694 00695 if ( $wgAllowUserCssPrefs ) { 00696 $defaultPreferences['justify'] = array( 00697 'type' => 'toggle', 00698 'section' => 'rendering/advancedrendering', 00699 'label-message' => 'tog-justify', 00700 ); 00701 } 00702 00703 $defaultPreferences['numberheadings'] = array( 00704 'type' => 'toggle', 00705 'section' => 'rendering/advancedrendering', 00706 'label-message' => 'tog-numberheadings', 00707 ); 00708 } 00709 00715 static function editingPreferences( $user, IContextSource $context, &$defaultPreferences ) { 00716 global $wgUseExternalEditor, $wgAllowUserCssPrefs; 00717 00718 ## Editing ##################################### 00719 $defaultPreferences['cols'] = array( 00720 'type' => 'int', 00721 'label-message' => 'columns', 00722 'section' => 'editing/textboxsize', 00723 'min' => 4, 00724 'max' => 1000, 00725 ); 00726 $defaultPreferences['rows'] = array( 00727 'type' => 'int', 00728 'label-message' => 'rows', 00729 'section' => 'editing/textboxsize', 00730 'min' => 4, 00731 'max' => 1000, 00732 ); 00733 00734 if ( $wgAllowUserCssPrefs ) { 00735 $defaultPreferences['editfont'] = array( 00736 'type' => 'select', 00737 'section' => 'editing/advancedediting', 00738 'label-message' => 'editfont-style', 00739 'options' => array( 00740 $context->msg( 'editfont-default' )->text() => 'default', 00741 $context->msg( 'editfont-monospace' )->text() => 'monospace', 00742 $context->msg( 'editfont-sansserif' )->text() => 'sans-serif', 00743 $context->msg( 'editfont-serif' )->text() => 'serif', 00744 ) 00745 ); 00746 } 00747 $defaultPreferences['previewontop'] = array( 00748 'type' => 'toggle', 00749 'section' => 'editing/advancedediting', 00750 'label-message' => 'tog-previewontop', 00751 ); 00752 $defaultPreferences['previewonfirst'] = array( 00753 'type' => 'toggle', 00754 'section' => 'editing/advancedediting', 00755 'label-message' => 'tog-previewonfirst', 00756 ); 00757 00758 if ( $wgAllowUserCssPrefs ) { 00759 $defaultPreferences['editsection'] = array( 00760 'type' => 'toggle', 00761 'section' => 'editing/advancedediting', 00762 'label-message' => 'tog-editsection', 00763 ); 00764 } 00765 $defaultPreferences['editsectiononrightclick'] = array( 00766 'type' => 'toggle', 00767 'section' => 'editing/advancedediting', 00768 'label-message' => 'tog-editsectiononrightclick', 00769 ); 00770 $defaultPreferences['editondblclick'] = array( 00771 'type' => 'toggle', 00772 'section' => 'editing/advancedediting', 00773 'label-message' => 'tog-editondblclick', 00774 ); 00775 $defaultPreferences['showtoolbar'] = array( 00776 'type' => 'toggle', 00777 'section' => 'editing/advancedediting', 00778 'label-message' => 'tog-showtoolbar', 00779 ); 00780 00781 if ( $user->isAllowed( 'minoredit' ) ) { 00782 $defaultPreferences['minordefault'] = array( 00783 'type' => 'toggle', 00784 'section' => 'editing/advancedediting', 00785 'label-message' => 'tog-minordefault', 00786 ); 00787 } 00788 00789 if ( $wgUseExternalEditor ) { 00790 $defaultPreferences['externaleditor'] = array( 00791 'type' => 'toggle', 00792 'section' => 'editing/advancedediting', 00793 'label-message' => 'tog-externaleditor', 00794 ); 00795 $defaultPreferences['externaldiff'] = array( 00796 'type' => 'toggle', 00797 'section' => 'editing/advancedediting', 00798 'label-message' => 'tog-externaldiff', 00799 ); 00800 } 00801 00802 $defaultPreferences['forceeditsummary'] = array( 00803 'type' => 'toggle', 00804 'section' => 'editing/advancedediting', 00805 'label-message' => 'tog-forceeditsummary', 00806 ); 00807 00808 00809 $defaultPreferences['uselivepreview'] = array( 00810 'type' => 'toggle', 00811 'section' => 'editing/advancedediting', 00812 'label-message' => 'tog-uselivepreview', 00813 ); 00814 } 00815 00821 static function rcPreferences( $user, IContextSource $context, &$defaultPreferences ) { 00822 global $wgRCMaxAge, $wgRCShowWatchingUsers; 00823 00824 ## RecentChanges ##################################### 00825 $defaultPreferences['rcdays'] = array( 00826 'type' => 'float', 00827 'label-message' => 'recentchangesdays', 00828 'section' => 'rc/displayrc', 00829 'min' => 1, 00830 'max' => ceil( $wgRCMaxAge / ( 3600 * 24 ) ), 00831 'help' => $context->msg( 'recentchangesdays-max' )->numParams( 00832 ceil( $wgRCMaxAge / ( 3600 * 24 ) ) )->text() 00833 ); 00834 $defaultPreferences['rclimit'] = array( 00835 'type' => 'int', 00836 'label-message' => 'recentchangescount', 00837 'help-message' => 'prefs-help-recentchangescount', 00838 'section' => 'rc/displayrc', 00839 ); 00840 $defaultPreferences['usenewrc'] = array( 00841 'type' => 'toggle', 00842 'label-message' => 'tog-usenewrc', 00843 'section' => 'rc/advancedrc', 00844 ); 00845 $defaultPreferences['hideminor'] = array( 00846 'type' => 'toggle', 00847 'label-message' => 'tog-hideminor', 00848 'section' => 'rc/advancedrc', 00849 ); 00850 00851 if ( $user->useRCPatrol() ) { 00852 $defaultPreferences['hidepatrolled'] = array( 00853 'type' => 'toggle', 00854 'section' => 'rc/advancedrc', 00855 'label-message' => 'tog-hidepatrolled', 00856 ); 00857 $defaultPreferences['newpageshidepatrolled'] = array( 00858 'type' => 'toggle', 00859 'section' => 'rc/advancedrc', 00860 'label-message' => 'tog-newpageshidepatrolled', 00861 ); 00862 } 00863 00864 if ( $wgRCShowWatchingUsers ) { 00865 $defaultPreferences['shownumberswatching'] = array( 00866 'type' => 'toggle', 00867 'section' => 'rc/advancedrc', 00868 'label-message' => 'tog-shownumberswatching', 00869 ); 00870 } 00871 } 00872 00878 static function watchlistPreferences( $user, IContextSource $context, &$defaultPreferences ) { 00879 global $wgUseRCPatrol, $wgEnableAPI, $wgRCMaxAge; 00880 00881 $watchlistdaysMax = ceil( $wgRCMaxAge / ( 3600 * 24 ) ); 00882 00883 ## Watchlist ##################################### 00884 $defaultPreferences['watchlistdays'] = array( 00885 'type' => 'float', 00886 'min' => 0, 00887 'max' => $watchlistdaysMax, 00888 'section' => 'watchlist/displaywatchlist', 00889 'help' => $context->msg( 'prefs-watchlist-days-max' )->numParams( 00890 $watchlistdaysMax )->text(), 00891 'label-message' => 'prefs-watchlist-days', 00892 ); 00893 $defaultPreferences['wllimit'] = array( 00894 'type' => 'int', 00895 'min' => 0, 00896 'max' => 1000, 00897 'label-message' => 'prefs-watchlist-edits', 00898 'help' => $context->msg( 'prefs-watchlist-edits-max' )->escaped(), 00899 'section' => 'watchlist/displaywatchlist', 00900 ); 00901 $defaultPreferences['extendwatchlist'] = array( 00902 'type' => 'toggle', 00903 'section' => 'watchlist/advancedwatchlist', 00904 'label-message' => 'tog-extendwatchlist', 00905 ); 00906 $defaultPreferences['watchlisthideminor'] = array( 00907 'type' => 'toggle', 00908 'section' => 'watchlist/advancedwatchlist', 00909 'label-message' => 'tog-watchlisthideminor', 00910 ); 00911 $defaultPreferences['watchlisthidebots'] = array( 00912 'type' => 'toggle', 00913 'section' => 'watchlist/advancedwatchlist', 00914 'label-message' => 'tog-watchlisthidebots', 00915 ); 00916 $defaultPreferences['watchlisthideown'] = array( 00917 'type' => 'toggle', 00918 'section' => 'watchlist/advancedwatchlist', 00919 'label-message' => 'tog-watchlisthideown', 00920 ); 00921 $defaultPreferences['watchlisthideanons'] = array( 00922 'type' => 'toggle', 00923 'section' => 'watchlist/advancedwatchlist', 00924 'label-message' => 'tog-watchlisthideanons', 00925 ); 00926 $defaultPreferences['watchlisthideliu'] = array( 00927 'type' => 'toggle', 00928 'section' => 'watchlist/advancedwatchlist', 00929 'label-message' => 'tog-watchlisthideliu', 00930 ); 00931 00932 if ( $wgUseRCPatrol ) { 00933 $defaultPreferences['watchlisthidepatrolled'] = array( 00934 'type' => 'toggle', 00935 'section' => 'watchlist/advancedwatchlist', 00936 'label-message' => 'tog-watchlisthidepatrolled', 00937 ); 00938 } 00939 00940 if ( $wgEnableAPI ) { 00941 # Some random gibberish as a proposed default 00942 // @todo Fixme: this should use CryptRand but we may not want to read urandom on every view 00943 $hash = sha1( mt_rand() . microtime( true ) ); 00944 00945 $defaultPreferences['watchlisttoken'] = array( 00946 'type' => 'text', 00947 'section' => 'watchlist/advancedwatchlist', 00948 'label-message' => 'prefs-watchlist-token', 00949 'help' => $context->msg( 'prefs-help-watchlist-token', $hash )->escaped() 00950 ); 00951 } 00952 00953 $watchTypes = array( 00954 'edit' => 'watchdefault', 00955 'move' => 'watchmoves', 00956 'delete' => 'watchdeletion' 00957 ); 00958 00959 // Kinda hacky 00960 if ( $user->isAllowed( 'createpage' ) || $user->isAllowed( 'createtalk' ) ) { 00961 $watchTypes['read'] = 'watchcreations'; 00962 } 00963 00964 foreach ( $watchTypes as $action => $pref ) { 00965 if ( $user->isAllowed( $action ) ) { 00966 $defaultPreferences[$pref] = array( 00967 'type' => 'toggle', 00968 'section' => 'watchlist/advancedwatchlist', 00969 'label-message' => "tog-$pref", 00970 ); 00971 } 00972 } 00973 } 00974 00980 static function searchPreferences( $user, IContextSource $context, &$defaultPreferences ) { 00981 global $wgContLang, $wgVectorUseSimpleSearch; 00982 00983 ## Search ##################################### 00984 $defaultPreferences['searchlimit'] = array( 00985 'type' => 'int', 00986 'label-message' => 'resultsperpage', 00987 'section' => 'searchoptions/displaysearchoptions', 00988 'min' => 0, 00989 ); 00990 00991 00992 if ( $wgVectorUseSimpleSearch ) { 00993 $defaultPreferences['vector-simplesearch'] = array( 00994 'type' => 'toggle', 00995 'label-message' => 'vector-simplesearch-preference', 00996 'section' => 'searchoptions/displaysearchoptions', 00997 ); 00998 } 00999 01000 $defaultPreferences['disablesuggest'] = array( 01001 'type' => 'toggle', 01002 'label-message' => 'mwsuggest-disable', 01003 'section' => 'searchoptions/displaysearchoptions', 01004 ); 01005 01006 $defaultPreferences['searcheverything'] = array( 01007 'type' => 'toggle', 01008 'label-message' => 'searcheverything-enable', 01009 'section' => 'searchoptions/advancedsearchoptions', 01010 ); 01011 01012 $nsOptions = array(); 01013 01014 foreach ( $wgContLang->getNamespaces() as $ns => $name ) { 01015 if ( $ns < 0 ) { 01016 continue; 01017 } 01018 01019 $displayNs = str_replace( '_', ' ', $name ); 01020 01021 if ( !$displayNs ) { 01022 $displayNs = $context->msg( 'blanknamespace' )->text(); 01023 } 01024 01025 $displayNs = htmlspecialchars( $displayNs ); 01026 $nsOptions[$displayNs] = $ns; 01027 } 01028 01029 $defaultPreferences['searchnamespaces'] = array( 01030 'type' => 'multiselect', 01031 'label-message' => 'defaultns', 01032 'options' => $nsOptions, 01033 'section' => 'searchoptions/advancedsearchoptions', 01034 'prefix' => 'searchNs', 01035 ); 01036 } 01037 01043 static function miscPreferences( $user, IContextSource $context, &$defaultPreferences ) { 01044 global $wgContLang; 01045 01046 ## Misc ##################################### 01047 $defaultPreferences['diffonly'] = array( 01048 'type' => 'toggle', 01049 'section' => 'misc/diffs', 01050 'label-message' => 'tog-diffonly', 01051 ); 01052 $defaultPreferences['norollbackdiff'] = array( 01053 'type' => 'toggle', 01054 'section' => 'misc/diffs', 01055 'label-message' => 'tog-norollbackdiff', 01056 ); 01057 01058 // Stuff from Language::getExtraUserToggles() 01059 $toggles = $wgContLang->getExtraUserToggles(); 01060 01061 foreach ( $toggles as $toggle ) { 01062 $defaultPreferences[$toggle] = array( 01063 'type' => 'toggle', 01064 'section' => 'personal/i18n', 01065 'label-message' => "tog-$toggle", 01066 ); 01067 } 01068 } 01069 01075 static function generateSkinOptions( $user, IContextSource $context ) { 01076 global $wgDefaultSkin, $wgAllowUserCss, $wgAllowUserJs; 01077 $ret = array(); 01078 01079 $mptitle = Title::newMainPage(); 01080 $previewtext = $context->msg( 'skin-preview' )->text(); 01081 01082 # Only show members of Skin::getSkinNames() rather than 01083 # $skinNames (skins is all skin names from Language.php) 01084 $validSkinNames = Skin::getUsableSkins(); 01085 01086 # Sort by UI skin name. First though need to update validSkinNames as sometimes 01087 # the skinkey & UI skinname differ (e.g. "standard" skinkey is "Classic" in the UI). 01088 foreach ( $validSkinNames as $skinkey => &$skinname ) { 01089 $msg = $context->msg( "skinname-{$skinkey}" ); 01090 if ( $msg->exists() ) { 01091 $skinname = htmlspecialchars( $msg->text() ); 01092 } 01093 } 01094 asort( $validSkinNames ); 01095 01096 foreach ( $validSkinNames as $skinkey => $sn ) { 01097 $linkTools = array(); 01098 01099 # Mark the default skin 01100 if ( $skinkey == $wgDefaultSkin ) { 01101 $linkTools[] = $context->msg( 'default' )->escaped(); 01102 } 01103 01104 # Create preview link 01105 $mplink = htmlspecialchars( $mptitle->getLocalURL( "useskin=$skinkey" ) ); 01106 $linkTools[] = "<a target='_blank' href=\"$mplink\">$previewtext</a>"; 01107 01108 # Create links to user CSS/JS pages 01109 if ( $wgAllowUserCss ) { 01110 $cssPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/' . $skinkey . '.css' ); 01111 $linkTools[] = Linker::link( $cssPage, $context->msg( 'prefs-custom-css' )->escaped() ); 01112 } 01113 01114 if ( $wgAllowUserJs ) { 01115 $jsPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/' . $skinkey . '.js' ); 01116 $linkTools[] = Linker::link( $jsPage, $context->msg( 'prefs-custom-js' )->escaped() ); 01117 } 01118 01119 $display = $sn . ' ' . $context->msg( 'parentheses', $context->getLanguage()->pipeList( $linkTools ) )->text(); 01120 $ret[$display] = $skinkey; 01121 } 01122 01123 return $ret; 01124 } 01125 01130 static function getDateOptions( IContextSource $context ) { 01131 $lang = $context->getLanguage(); 01132 $dateopts = $lang->getDatePreferences(); 01133 01134 $ret = array(); 01135 01136 if ( $dateopts ) { 01137 if ( !in_array( 'default', $dateopts ) ) { 01138 $dateopts[] = 'default'; // Make sure default is always valid 01139 // Bug 19237 01140 } 01141 01142 // KLUGE: site default might not be valid for user language 01143 global $wgDefaultUserOptions; 01144 if ( !in_array( $wgDefaultUserOptions['date'], $dateopts ) ) { 01145 $wgDefaultUserOptions['date'] = 'default'; 01146 } 01147 01148 $epoch = wfTimestampNow(); 01149 foreach ( $dateopts as $key ) { 01150 if ( $key == 'default' ) { 01151 $formatted = $context->msg( 'datedefault' )->escaped(); 01152 } else { 01153 $formatted = htmlspecialchars( $lang->timeanddate( $epoch, false, $key ) ); 01154 } 01155 $ret[$formatted] = $key; 01156 } 01157 } 01158 return $ret; 01159 } 01160 01165 static function getImageSizes( IContextSource $context ) { 01166 global $wgImageLimits; 01167 01168 $ret = array(); 01169 $pixels = $context->msg( 'unit-pixel' )->text(); 01170 01171 foreach ( $wgImageLimits as $index => $limits ) { 01172 $display = "{$limits[0]}×{$limits[1]}" . $pixels; 01173 $ret[$display] = $index; 01174 } 01175 01176 return $ret; 01177 } 01178 01183 static function getThumbSizes( IContextSource $context ) { 01184 global $wgThumbLimits; 01185 01186 $ret = array(); 01187 $pixels = $context->msg( 'unit-pixel' )->text(); 01188 01189 foreach ( $wgThumbLimits as $index => $size ) { 01190 $display = $size . $pixels; 01191 $ret[$display] = $index; 01192 } 01193 01194 return $ret; 01195 } 01196 01203 static function validateSignature( $signature, $alldata, $form ) { 01204 global $wgParser, $wgMaxSigChars; 01205 if ( mb_strlen( $signature ) > $wgMaxSigChars ) { 01206 return Xml::element( 'span', array( 'class' => 'error' ), 01207 $form->msg( 'badsiglength' )->numParams( $wgMaxSigChars )->text() ); 01208 } elseif ( isset( $alldata['fancysig'] ) && 01209 $alldata['fancysig'] && 01210 false === $wgParser->validateSig( $signature ) ) { 01211 return Xml::element( 'span', array( 'class' => 'error' ), $form->msg( 'badsig' )->text() ); 01212 } else { 01213 return true; 01214 } 01215 } 01216 01223 static function cleanSignature( $signature, $alldata, $form ) { 01224 if ( isset( $alldata['fancysig'] ) && $alldata['fancysig'] ) { 01225 global $wgParser; 01226 $signature = $wgParser->cleanSig( $signature ); 01227 } else { 01228 // When no fancy sig used, make sure ~{3,5} get removed. 01229 $signature = Parser::cleanSigInSig( $signature ); 01230 } 01231 01232 return $signature; 01233 } 01234 01242 static function getFormObject( $user, IContextSource $context, $formClass = 'PreferencesForm', array $remove = array() ) { 01243 $formDescriptor = Preferences::getPreferences( $user, $context ); 01244 if ( count( $remove ) ) { 01245 $removeKeys = array_flip( $remove ); 01246 $formDescriptor = array_diff_key( $formDescriptor, $removeKeys ); 01247 } 01248 01249 // Remove type=api preferences. They are not intended for rendering in the form. 01250 foreach ( $formDescriptor as $name => $info ) { 01251 if ( isset( $info['type'] ) && $info['type'] === 'api' ) { 01252 unset( $formDescriptor[$name] ); 01253 } 01254 } 01255 01259 $htmlForm = new $formClass( $formDescriptor, $context, 'prefs' ); 01260 01261 $htmlForm->setModifiedUser( $user ); 01262 $htmlForm->setId( 'mw-prefs-form' ); 01263 $htmlForm->setSubmitText( $context->msg( 'saveprefs' )->text() ); 01264 # Used message keys: 'accesskey-preferences-save', 'tooltip-preferences-save' 01265 $htmlForm->setSubmitTooltip( 'preferences-save' ); 01266 $htmlForm->setSubmitID( 'prefsubmit' ); 01267 $htmlForm->setSubmitCallback( array( 'Preferences', 'tryFormSubmit' ) ); 01268 01269 return $htmlForm; 01270 } 01271 01275 static function getTimezoneOptions( IContextSource $context ) { 01276 $opt = array(); 01277 01278 global $wgLocalTZoffset, $wgLocaltimezone; 01279 // Check that $wgLocalTZoffset is the same as $wgLocaltimezone 01280 if ( $wgLocalTZoffset == date( 'Z' ) / 60 ) { 01281 $server_tz_msg = $context->msg( 'timezoneuseserverdefault', $wgLocaltimezone )->text(); 01282 } else { 01283 $tzstring = sprintf( '%+03d:%02d', floor( $wgLocalTZoffset / 60 ), abs( $wgLocalTZoffset ) % 60 ); 01284 $server_tz_msg = $context->msg( 'timezoneuseserverdefault', $tzstring )->text(); 01285 } 01286 $opt[$server_tz_msg] = "System|$wgLocalTZoffset"; 01287 $opt[$context->msg( 'timezoneuseoffset' )->text()] = 'other'; 01288 $opt[$context->msg( 'guesstimezone' )->text()] = 'guess'; 01289 01290 if ( function_exists( 'timezone_identifiers_list' ) ) { 01291 # Read timezone list 01292 $tzs = timezone_identifiers_list(); 01293 sort( $tzs ); 01294 01295 $tzRegions = array(); 01296 $tzRegions['Africa'] = $context->msg( 'timezoneregion-africa' )->text(); 01297 $tzRegions['America'] = $context->msg( 'timezoneregion-america' )->text(); 01298 $tzRegions['Antarctica'] = $context->msg( 'timezoneregion-antarctica' )->text(); 01299 $tzRegions['Arctic'] = $context->msg( 'timezoneregion-arctic' )->text(); 01300 $tzRegions['Asia'] = $context->msg( 'timezoneregion-asia' )->text(); 01301 $tzRegions['Atlantic'] = $context->msg( 'timezoneregion-atlantic' )->text(); 01302 $tzRegions['Australia'] = $context->msg( 'timezoneregion-australia' )->text(); 01303 $tzRegions['Europe'] = $context->msg( 'timezoneregion-europe' )->text(); 01304 $tzRegions['Indian'] = $context->msg( 'timezoneregion-indian' )->text(); 01305 $tzRegions['Pacific'] = $context->msg( 'timezoneregion-pacific' )->text(); 01306 asort( $tzRegions ); 01307 01308 $prefill = array_fill_keys( array_values( $tzRegions ), array() ); 01309 $opt = array_merge( $opt, $prefill ); 01310 01311 $now = date_create( 'now' ); 01312 01313 foreach ( $tzs as $tz ) { 01314 $z = explode( '/', $tz, 2 ); 01315 01316 # timezone_identifiers_list() returns a number of 01317 # backwards-compatibility entries. This filters them out of the 01318 # list presented to the user. 01319 if ( count( $z ) != 2 || !array_key_exists( $z[0], $tzRegions ) ) { 01320 continue; 01321 } 01322 01323 # Localize region 01324 $z[0] = $tzRegions[$z[0]]; 01325 01326 $minDiff = floor( timezone_offset_get( timezone_open( $tz ), $now ) / 60 ); 01327 01328 $display = str_replace( '_', ' ', $z[0] . '/' . $z[1] ); 01329 $value = "ZoneInfo|$minDiff|$tz"; 01330 01331 $opt[$z[0]][$display] = $value; 01332 } 01333 } 01334 return $opt; 01335 } 01336 01342 static function filterIntval( $value, $alldata ){ 01343 return intval( $value ); 01344 } 01345 01351 static function filterTimezoneInput( $tz, $alldata ) { 01352 $data = explode( '|', $tz, 3 ); 01353 switch ( $data[0] ) { 01354 case 'ZoneInfo': 01355 case 'System': 01356 return $tz; 01357 default: 01358 $data = explode( ':', $tz, 2 ); 01359 if ( count( $data ) == 2 ) { 01360 $data[0] = intval( $data[0] ); 01361 $data[1] = intval( $data[1] ); 01362 $minDiff = abs( $data[0] ) * 60 + $data[1]; 01363 if ( $data[0] < 0 ) $minDiff = - $minDiff; 01364 } else { 01365 $minDiff = intval( $data[0] ) * 60; 01366 } 01367 01368 # Max is +14:00 and min is -12:00, see: 01369 # http://en.wikipedia.org/wiki/Timezone 01370 $minDiff = min( $minDiff, 840 ); # 14:00 01371 $minDiff = max( $minDiff, - 720 ); # -12:00 01372 return 'Offset|' . $minDiff; 01373 } 01374 } 01375 01382 static function tryFormSubmit( $formData, $form, $entryPoint = 'internal' ) { 01383 global $wgHiddenPrefs; 01384 01385 $user = $form->getModifiedUser(); 01386 $result = true; 01387 01388 // Filter input 01389 foreach ( array_keys( $formData ) as $name ) { 01390 if ( isset( self::$saveFilters[$name] ) ) { 01391 $formData[$name] = 01392 call_user_func( self::$saveFilters[$name], $formData[$name], $formData ); 01393 } 01394 } 01395 01396 // Stuff that shouldn't be saved as a preference. 01397 $saveBlacklist = array( 01398 'realname', 01399 'emailaddress', 01400 ); 01401 01402 // Fortunately, the realname field is MUCH simpler 01403 if ( !in_array( 'realname', $wgHiddenPrefs ) ) { 01404 $realName = $formData['realname']; 01405 $user->setRealName( $realName ); 01406 } 01407 01408 foreach ( $saveBlacklist as $b ) { 01409 unset( $formData[$b] ); 01410 } 01411 01412 # If users have saved a value for a preference which has subsequently been disabled 01413 # via $wgHiddenPrefs, we don't want to destroy that setting in case the preference 01414 # is subsequently re-enabled 01415 # TODO: maintenance script to actually delete these 01416 foreach( $wgHiddenPrefs as $pref ){ 01417 # If the user has not set a non-default value here, the default will be returned 01418 # and subsequently discarded 01419 $formData[$pref] = $user->getOption( $pref, null, true ); 01420 } 01421 01422 // Keeps old preferences from interfering due to back-compat 01423 // code, etc. 01424 $user->resetOptions(); 01425 01426 foreach ( $formData as $key => $value ) { 01427 $user->setOption( $key, $value ); 01428 } 01429 01430 $user->saveSettings(); 01431 01432 return $result; 01433 } 01434 01440 public static function tryUISubmit( $formData, $form ) { 01441 $res = self::tryFormSubmit( $formData, $form, 'ui' ); 01442 01443 if ( $res ) { 01444 $urlOptions = array( 'success' => 1 ); 01445 01446 if ( $res === 'eauth' ) { 01447 $urlOptions['eauth'] = 1; 01448 } 01449 01450 $urlOptions += $form->getExtraSuccessRedirectParameters(); 01451 01452 $url = $form->getTitle()->getFullURL( $urlOptions ); 01453 01454 $form->getContext()->getOutput()->redirect( $url ); 01455 } 01456 01457 return Status::newGood(); 01458 } 01459 01470 public static function trySetUserEmail( User $user, $newaddr ) { 01471 wfDeprecated( __METHOD__, '1.20' ); 01472 01473 $result = $user->setEmailWithConfirmation( $newaddr ); 01474 if ( $result->isGood() ) { 01475 return array( true, $result->value ); 01476 } else { 01477 return array( $result, 'mailerror' ); 01478 } 01479 } 01480 01486 public static function loadOldSearchNs( $user ) { 01487 wfDeprecated( __METHOD__, '1.19' ); 01488 01489 $searchableNamespaces = SearchEngine::searchableNamespaces(); 01490 // Back compat with old format 01491 $arr = array(); 01492 01493 foreach ( $searchableNamespaces as $ns => $name ) { 01494 if ( $user->getOption( 'searchNs' . $ns ) ) { 01495 $arr[] = $ns; 01496 } 01497 } 01498 01499 return $arr; 01500 } 01501 } 01502 01504 class PreferencesForm extends HTMLForm { 01505 // Override default value from HTMLForm 01506 protected $mSubSectionBeforeFields = false; 01507 01508 private $modifiedUser; 01509 01513 public function setModifiedUser( $user ) { 01514 $this->modifiedUser = $user; 01515 } 01516 01520 public function getModifiedUser() { 01521 if ( $this->modifiedUser === null ) { 01522 return $this->getUser(); 01523 } else { 01524 return $this->modifiedUser; 01525 } 01526 } 01527 01534 public function getExtraSuccessRedirectParameters() { 01535 return array(); 01536 } 01537 01542 function wrapForm( $html ) { 01543 $html = Xml::tags( 'div', array( 'id' => 'preferences' ), $html ); 01544 01545 return parent::wrapForm( $html ); 01546 } 01547 01551 function getButtons() { 01552 $html = parent::getButtons(); 01553 01554 $t = SpecialPage::getTitleFor( 'Preferences', 'reset' ); 01555 01556 $html .= "\n" . Linker::link( $t, $this->msg( 'restoreprefs' )->escaped() ); 01557 01558 $html = Xml::tags( 'div', array( 'class' => 'mw-prefs-buttons' ), $html ); 01559 01560 return $html; 01561 } 01562 01567 function filterDataForSubmit( $data ) { 01568 // Support for separating MultiSelect preferences into multiple preferences 01569 // Due to lack of array support. 01570 foreach ( $this->mFlatFields as $fieldname => $field ) { 01571 $info = $field->mParams; 01572 if ( $field instanceof HTMLMultiSelectField ) { 01573 $options = HTMLFormField::flattenOptions( $info['options'] ); 01574 $prefix = isset( $info['prefix'] ) ? $info['prefix'] : $fieldname; 01575 01576 foreach ( $options as $opt ) { 01577 $data["$prefix$opt"] = in_array( $opt, $data[$fieldname] ); 01578 } 01579 01580 unset( $data[$fieldname] ); 01581 } 01582 } 01583 01584 return $data; 01585 } 01586 01591 function getBody() { 01592 return $this->displaySection( $this->mFieldTree, '', 'mw-prefsection-' ); 01593 } 01594 01601 function getLegend( $key ) { 01602 $legend = parent::getLegend( $key ); 01603 wfRunHooks( 'PreferencesGetLegend', array( $this, $key, &$legend ) ); 01604 return $legend; 01605 } 01606 }