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