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