MediaWiki  REL1_19
Preferences.php
Go to the documentation of this file.
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' => '&#160;',
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' => '&#160;',
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 }