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