diff options
Diffstat (limited to 'includes/Preferences.php')
-rw-r--r-- | includes/Preferences.php | 596 |
1 files changed, 319 insertions, 277 deletions
diff --git a/includes/Preferences.php b/includes/Preferences.php index db231573..c9caf4f7 100644 --- a/includes/Preferences.php +++ b/includes/Preferences.php @@ -1,6 +1,6 @@ <?php /** - * Form to edit user perferences. + * Form to edit user preferences. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -56,6 +56,12 @@ class Preferences { 'searchlimit' => array( 'Preferences', 'filterIntval' ), ); + // Stuff that shouldn't be saved as a preference. + private static $saveBlacklist = array( + 'realname', + 'emailaddress', + ); + /** * @throws MWException * @param $user User @@ -90,10 +96,19 @@ class Preferences { } } + ## Make sure that form fields have their parent set. See bug 41337. + $dummyForm = new HTMLForm( array(), $context ); + + $disable = !$user->isAllowed( 'editmyoptions' ); + ## Prod in defaults from the user foreach ( $defaultPreferences as $name => &$info ) { $prefFromUser = self::getOptionFromUser( $name, $info, $user ); + if ( $disable && !in_array( $name, self::$saveBlacklist ) ) { + $info['disabled'] = 'disabled'; + } $field = HTMLForm::loadInputFromParameters( $name, $info ); // For validation + $field->mParent = $dummyForm; $defaultOptions = User::getDefaultOptions(); $globalDefault = isset( $defaultOptions[$name] ) ? $defaultOptions[$name] @@ -129,7 +144,7 @@ class Preferences { static function getOptionFromUser( $name, $info, $user ) { $val = $user->getOption( $name ); - // Handling for array-type preferences + // Handling for multiselect preferences if ( ( isset( $info['type'] ) && $info['type'] == 'multiselect' ) || ( isset( $info['class'] ) && $info['class'] == 'HTMLMultiSelectField' ) ) { $options = HTMLFormField::flattenOptions( $info['options'] ); @@ -143,6 +158,23 @@ class Preferences { } } + // Handling for checkmatrix preferences + if ( ( isset( $info['type'] ) && $info['type'] == 'checkmatrix' ) || + ( isset( $info['class'] ) && $info['class'] == 'HTMLCheckMatrix' ) ) { + $columns = HTMLFormField::flattenOptions( $info['columns'] ); + $rows = HTMLFormField::flattenOptions( $info['rows'] ); + $prefix = isset( $info['prefix'] ) ? $info['prefix'] : $name; + $val = array(); + + foreach ( $columns as $column ) { + foreach ( $rows as $row ) { + if ( $user->getOption( "$prefix$column-$row" ) ) { + $val[] = "$column-$row"; + } + } + } + } + return $val; } @@ -156,20 +188,24 @@ class Preferences { global $wgAuth, $wgContLang, $wgParser, $wgCookieExpiration, $wgLanguageCode, $wgDisableTitleConversion, $wgDisableLangConversion, $wgMaxSigChars, $wgEnableEmail, $wgEmailConfirmToEdit, $wgEnableUserEmail, $wgEmailAuthentication, - $wgEnotifWatchlist, $wgEnotifUserTalk, $wgEnotifRevealEditorAddress; + $wgEnotifWatchlist, $wgEnotifUserTalk, $wgEnotifRevealEditorAddress, + $wgSecureLogin; + + // retrieving user name for GENDER and misc. + $userName = $user->getName(); ## User info ##################################### // Information panel $defaultPreferences['username'] = array( 'type' => 'info', - 'label-message' => 'username', - 'default' => $user->getName(), + 'label-message' => array( 'username', $userName ), + 'default' => $userName, 'section' => 'personal/info', ); $defaultPreferences['userid'] = array( 'type' => 'info', - 'label-message' => 'uid', + 'label-message' => array( 'uid', $userName ), 'default' => $user->getId(), 'section' => 'personal/info', ); @@ -182,10 +218,10 @@ class Preferences { // Skip the default * group, seems useless here continue; } - $groupName = User::getGroupName( $ueg ); + $groupName = User::getGroupName( $ueg ); $userGroups[] = User::makeGroupLinkHTML( $ueg, $groupName ); - $memberName = User::getGroupMember( $ueg, $user->getName() ); + $memberName = User::getGroupMember( $ueg, $userName ); $userMembers[] = User::makeGroupLinkHTML( $ueg, $memberName ); } asort( $userGroups ); @@ -196,7 +232,7 @@ class Preferences { $defaultPreferences['usergroups'] = array( 'type' => 'info', 'label' => $context->msg( 'prefs-memberingroups' )->numParams( - count( $userGroups ) )->parse(), + count( $userGroups ) )->params( $userName )->parse(), 'default' => $context->msg( 'prefs-memberingroups-type', $lang->commaList( $userGroups ), $lang->commaList( $userMembers ) @@ -205,10 +241,14 @@ class Preferences { 'section' => 'personal/info', ); + $editCount = Linker::link( SpecialPage::getTitleFor( "Contributions", $userName ), + $lang->formatNum( $user->getEditCount() ) ); + $defaultPreferences['editcount'] = array( 'type' => 'info', + 'raw' => true, 'label-message' => 'prefs-edits', - 'default' => $lang->formatNum( $user->getEditCount() ), + 'default' => $editCount, 'section' => 'personal/info', ); @@ -228,31 +268,23 @@ class Preferences { ); } + $canViewPrivateInfo = $user->isAllowed( 'viewmyprivateinfo' ); + $canEditPrivateInfo = $user->isAllowed( 'editmyprivateinfo' ); + // Actually changeable stuff $defaultPreferences['realname'] = array( - 'type' => $wgAuth->allowPropChange( 'realname' ) ? 'text' : 'info', + // (not really "private", but still shouldn't be edited without permission) + 'type' => $canEditPrivateInfo && $wgAuth->allowPropChange( 'realname' ) ? 'text' : 'info', 'default' => $user->getRealName(), 'section' => 'personal/info', 'label-message' => 'yourrealname', 'help-message' => 'prefs-help-realname', ); - $defaultPreferences['gender'] = array( - 'type' => 'select', - 'section' => 'personal/info', - 'options' => array( - $context->msg( 'gender-male' )->text() => 'male', - $context->msg( 'gender-female' )->text() => 'female', - $context->msg( 'gender-unknown' )->text() => 'unknown', - ), - 'label-message' => 'yourgender', - 'help-message' => 'prefs-help-gender', - ); - - if ( $wgAuth->allowPasswordChange() ) { + if ( $canEditPrivateInfo && $wgAuth->allowPasswordChange() ) { $link = Linker::link( SpecialPage::getTitleFor( 'ChangePassword' ), $context->msg( 'prefs-resetpass' )->escaped(), array(), - array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' ) ) ); + array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ) ); $defaultPreferences['password'] = array( 'type' => 'info', @@ -270,6 +302,15 @@ class Preferences { 'section' => 'personal/info', ); } + // Only show preferhttps if secure login is turned on + if ( $wgSecureLogin && wfCanIPUseHTTPS( $context->getRequest()->getIP() ) ) { + $defaultPreferences['prefershttps'] = array( + 'type' => 'toggle', + 'label-message' => 'tog-prefershttps', + 'help-message' => 'prefs-help-prefershttps', + 'section' => 'personal/info' + ); + } // Language $languages = Language::fetchLanguageNames( null, 'mw' ); @@ -290,39 +331,74 @@ class Preferences { 'label-message' => 'yourlanguage', ); - /* see if there are multiple language variants to choose from*/ - $variantArray = array(); + $defaultPreferences['gender'] = array( + 'type' => 'radio', + 'section' => 'personal/i18n', + 'options' => array( + $context->msg( 'parentheses', + $context->msg( 'gender-unknown' )->text() + )->text() => 'unknown', + $context->msg( 'gender-female' )->text() => 'female', + $context->msg( 'gender-male' )->text() => 'male', + ), + 'label-message' => 'yourgender', + 'help-message' => 'prefs-help-gender', + ); + + // see if there are multiple language variants to choose from if ( !$wgDisableLangConversion ) { - $variants = $wgContLang->getVariants(); + foreach ( LanguageConverter::$languagesWithVariants as $langCode ) { + if ( $langCode == $wgContLang->getCode() ) { + $variants = $wgContLang->getVariants(); - foreach ( $variants as $v ) { - $v = str_replace( '_', '-', strtolower( $v ) ); - $variantArray[$v] = $wgContLang->getVariantname( $v, false ); - } + if ( count( $variants ) <= 1 ) { + continue; + } - $options = array(); - foreach ( $variantArray as $code => $name ) { - $display = wfBCP47( $code ) . ' - ' . $name; - $options[$display] = $code; - } + $variantArray = array(); + foreach ( $variants as $v ) { + $v = str_replace( '_', '-', strtolower( $v ) ); + $variantArray[$v] = $lang->getVariantname( $v, false ); + } - if ( count( $variantArray ) > 1 ) { - $defaultPreferences['variant'] = array( - 'label-message' => 'yourvariant', - 'type' => 'select', - 'options' => $options, - 'section' => 'personal/i18n', - 'help-message' => 'prefs-help-variant', - ); + $options = array(); + foreach ( $variantArray as $code => $name ) { + $display = wfBCP47( $code ) . ' - ' . $name; + $options[$display] = $code; + } + + $defaultPreferences['variant'] = array( + 'label-message' => 'yourvariant', + 'type' => 'select', + 'options' => $options, + 'section' => 'personal/i18n', + 'help-message' => 'prefs-help-variant', + ); + + if ( !$wgDisableTitleConversion ) { + $defaultPreferences['noconvertlink'] = array( + 'type' => 'toggle', + 'section' => 'personal/i18n', + 'label-message' => 'tog-noconvertlink', + ); + } + } else { + $defaultPreferences["variant-$langCode"] = array( + 'type' => 'api', + ); + } } } - if ( count( $variantArray ) > 1 && !$wgDisableLangConversion && !$wgDisableTitleConversion ) { - $defaultPreferences['noconvertlink'] = - array( + // Stuff from Language::getExtraUserToggles() + // FIXME is this dead code? $extraUserToggles doesn't seem to be defined for any language + $toggles = $wgContLang->getExtraUserToggles(); + + foreach ( $toggles as $toggle ) { + $defaultPreferences[$toggle] = array( 'type' => 'toggle', 'section' => 'personal/i18n', - 'label-message' => 'tog-noconvertlink', + 'label-message' => "tog-$toggle", ); } @@ -354,44 +430,45 @@ class Preferences { ## Email stuff if ( $wgEnableEmail ) { - $helpMessages[] = $wgEmailConfirmToEdit - ? 'prefs-help-email-required' - : 'prefs-help-email' ; + if ( $canViewPrivateInfo ) { + $helpMessages[] = $wgEmailConfirmToEdit + ? 'prefs-help-email-required' + : 'prefs-help-email'; + + if ( $wgEnableUserEmail ) { + // additional messages when users can send email to each other + $helpMessages[] = 'prefs-help-email-others'; + } - if( $wgEnableUserEmail ) { - // additional messages when users can send email to each other - $helpMessages[] = 'prefs-help-email-others'; - } + $emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : ''; + if ( $canEditPrivateInfo && $wgAuth->allowPropChange( 'emailaddress' ) ) { + $link = Linker::link( + SpecialPage::getTitleFor( 'ChangeEmail' ), + $context->msg( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->escaped(), + array(), + array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' )->getPrefixedText() ) ); + + $emailAddress .= $emailAddress == '' ? $link : ( + $context->msg( 'word-separator' )->plain() + . $context->msg( 'parentheses' )->rawParams( $link )->plain() + ); + } - $link = Linker::link( - SpecialPage::getTitleFor( 'ChangeEmail' ), - $context->msg( $user->getEmail() ? 'prefs-changeemail' : 'prefs-setemail' )->escaped(), - array(), - array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' ) ) ); - - $emailAddress = $user->getEmail() ? htmlspecialchars( $user->getEmail() ) : ''; - if ( $wgAuth->allowPropChange( 'emailaddress' ) ) { - $emailAddress .= $emailAddress == '' ? $link : ( - $context->msg( 'word-separator' )->plain() - . $context->msg( 'parentheses' )->rawParams( $link )->plain() + $defaultPreferences['emailaddress'] = array( + 'type' => 'info', + 'raw' => true, + 'default' => $emailAddress, + 'label-message' => 'youremail', + 'section' => 'personal/email', + 'help-messages' => $helpMessages, + # 'cssclass' chosen below ); } - - $defaultPreferences['emailaddress'] = array( - 'type' => 'info', - 'raw' => true, - 'default' => $emailAddress, - 'label-message' => 'youremail', - 'section' => 'personal/email', - 'help-messages' => $helpMessages, - # 'cssclass' chosen below - ); - $disableEmailPrefs = false; - $emailauthenticationclass = 'mw-email-not-authenticated'; if ( $wgEmailAuthentication ) { + $emailauthenticationclass = 'mw-email-not-authenticated'; if ( $user->getEmail() ) { if ( $user->getEmailAuthenticationTimestamp() ) { // date and time are separate parameters to facilitate localisation. @@ -413,7 +490,7 @@ class Preferences { SpecialPage::getTitleFor( 'Confirmemail' ), $context->msg( 'emailconfirmlink' )->escaped() ) . '<br />'; - $emailauthenticationclass="mw-email-not-authenticated"; + $emailauthenticationclass = "mw-email-not-authenticated"; } } else { $disableEmailPrefs = true; @@ -421,17 +498,19 @@ class Preferences { $emailauthenticationclass = 'mw-email-none'; } - $defaultPreferences['emailauthentication'] = array( - 'type' => 'info', - 'raw' => true, - 'section' => 'personal/email', - 'label-message' => 'prefs-emailconfirm-label', - 'default' => $emailauthenticated, - # Apply the same CSS class used on the input to the message: - 'cssclass' => $emailauthenticationclass, - ); + if ( $canViewPrivateInfo ) { + $defaultPreferences['emailauthentication'] = array( + 'type' => 'info', + 'raw' => true, + 'section' => 'personal/email', + 'label-message' => 'prefs-emailconfirm-label', + 'default' => $emailauthenticated, + # Apply the same CSS class used on the input to the message: + 'cssclass' => $emailauthenticationclass, + ); + $defaultPreferences['emailaddress']['cssclass'] = $emailauthenticationclass; + } } - $defaultPreferences['emailaddress']['cssclass'] = $emailauthenticationclass; if ( $wgEnableUserEmail && $user->isAllowed( 'sendemail' ) ) { $defaultPreferences['disablemail'] = array( @@ -507,14 +586,15 @@ class Preferences { # be nice to somehow merge this back in there to avoid redundancy. if ( $wgAllowUserCss || $wgAllowUserJs ) { $linkTools = array(); + $userName = $user->getName(); if ( $wgAllowUserCss ) { - $cssPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/common.css' ); + $cssPage = Title::makeTitleSafe( NS_USER, $userName . '/common.css' ); $linkTools[] = Linker::link( $cssPage, $context->msg( 'prefs-custom-css' )->escaped() ); } if ( $wgAllowUserJs ) { - $jsPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/common.js' ); + $jsPage = Title::makeTitleSafe( NS_USER, $userName . '/common.js' ); $linkTools[] = Linker::link( $jsPage, $context->msg( 'prefs-custom-js' )->escaped() ); } @@ -526,18 +606,6 @@ class Preferences { 'section' => 'rendering/skin', ); } - - $selectedSkin = $user->getOption( 'skin' ); - if ( in_array( $selectedSkin, array( 'cologneblue', 'standard' ) ) ) { - $settings = array_flip( $context->getLanguage()->getQuickbarSettings() ); - - $defaultPreferences['quickbar'] = array( - 'type' => 'radio', - 'options' => $settings, - 'section' => 'rendering/skin', - 'label-message' => 'qbsettings', - ); - } } /** @@ -640,6 +708,18 @@ class Preferences { * @param $defaultPreferences Array */ static function renderingPreferences( $user, IContextSource $context, &$defaultPreferences ) { + ## Diffs #################################### + $defaultPreferences['diffonly'] = array( + 'type' => 'toggle', + 'section' => 'rendering/diffs', + 'label-message' => 'tog-diffonly', + ); + $defaultPreferences['norollbackdiff'] = array( + 'type' => 'toggle', + 'section' => 'rendering/diffs', + 'label-message' => 'tog-norollbackdiff', + ); + ## Page Rendering ############################## global $wgAllowUserCssPrefs; if ( $wgAllowUserCssPrefs ) { @@ -666,7 +746,7 @@ class Preferences { 'section' => 'rendering/advancedrendering', 'options' => $stubThresholdOptions, 'size' => 20, - 'label' => $context->msg( 'stub-threshold' )->text(), // Raw HTML message. Yay? + 'label-raw' => $context->msg( 'stub-threshold' )->text(), // Raw HTML message. Yay? ); if ( $wgAllowUserCssPrefs ) { @@ -686,11 +766,6 @@ class Preferences { 'section' => 'rendering/advancedrendering', 'label-message' => 'tog-showhiddencats' ); - $defaultPreferences['showjumplinks'] = array( - 'type' => 'toggle', - 'section' => 'rendering/advancedrendering', - 'label-message' => 'tog-showjumplinks', - ); if ( $wgAllowUserCssPrefs ) { $defaultPreferences['justify'] = array( @@ -713,28 +788,31 @@ class Preferences { * @param $defaultPreferences Array */ static function editingPreferences( $user, IContextSource $context, &$defaultPreferences ) { - global $wgUseExternalEditor, $wgAllowUserCssPrefs; + global $wgAllowUserCssPrefs; ## Editing ##################################### - $defaultPreferences['cols'] = array( - 'type' => 'int', - 'label-message' => 'columns', - 'section' => 'editing/textboxsize', - 'min' => 4, - 'max' => 1000, + if ( $wgAllowUserCssPrefs ) { + $defaultPreferences['editsection'] = array( + 'type' => 'toggle', + 'section' => 'editing/advancedediting', + 'label-message' => 'tog-editsection', + ); + } + $defaultPreferences['editsectiononrightclick'] = array( + 'type' => 'toggle', + 'section' => 'editing/advancedediting', + 'label-message' => 'tog-editsectiononrightclick', ); - $defaultPreferences['rows'] = array( - 'type' => 'int', - 'label-message' => 'rows', - 'section' => 'editing/textboxsize', - 'min' => 4, - 'max' => 1000, + $defaultPreferences['editondblclick'] = array( + 'type' => 'toggle', + 'section' => 'editing/advancedediting', + 'label-message' => 'tog-editondblclick', ); if ( $wgAllowUserCssPrefs ) { $defaultPreferences['editfont'] = array( 'type' => 'select', - 'section' => 'editing/advancedediting', + 'section' => 'editing/editor', 'label-message' => 'editfont-style', 'options' => array( $context->msg( 'editfont-default' )->text() => 'default', @@ -744,73 +822,59 @@ class Preferences { ) ); } - $defaultPreferences['previewontop'] = array( - 'type' => 'toggle', - 'section' => 'editing/advancedediting', - 'label-message' => 'tog-previewontop', + $defaultPreferences['cols'] = array( + 'type' => 'int', + 'label-message' => 'columns', + 'section' => 'editing/editor', + 'min' => 4, + 'max' => 1000, ); - $defaultPreferences['previewonfirst'] = array( - 'type' => 'toggle', - 'section' => 'editing/advancedediting', - 'label-message' => 'tog-previewonfirst', + $defaultPreferences['rows'] = array( + 'type' => 'int', + 'label-message' => 'rows', + 'section' => 'editing/editor', + 'min' => 4, + 'max' => 1000, ); - - if ( $wgAllowUserCssPrefs ) { - $defaultPreferences['editsection'] = array( + if ( $user->isAllowed( 'minoredit' ) ) { + $defaultPreferences['minordefault'] = array( 'type' => 'toggle', - 'section' => 'editing/advancedediting', - 'label-message' => 'tog-editsection', + 'section' => 'editing/editor', + 'label-message' => 'tog-minordefault', ); } - $defaultPreferences['editsectiononrightclick'] = array( + $defaultPreferences['forceeditsummary'] = array( 'type' => 'toggle', - 'section' => 'editing/advancedediting', - 'label-message' => 'tog-editsectiononrightclick', + 'section' => 'editing/editor', + 'label-message' => 'tog-forceeditsummary', ); - $defaultPreferences['editondblclick'] = array( + $defaultPreferences['useeditwarning'] = array( 'type' => 'toggle', - 'section' => 'editing/advancedediting', - 'label-message' => 'tog-editondblclick', + 'section' => 'editing/editor', + 'label-message' => 'tog-useeditwarning', ); $defaultPreferences['showtoolbar'] = array( 'type' => 'toggle', - 'section' => 'editing/advancedediting', + 'section' => 'editing/editor', 'label-message' => 'tog-showtoolbar', ); - if ( $user->isAllowed( 'minoredit' ) ) { - $defaultPreferences['minordefault'] = array( - 'type' => 'toggle', - 'section' => 'editing/advancedediting', - 'label-message' => 'tog-minordefault', - ); - } - - if ( $wgUseExternalEditor ) { - $defaultPreferences['externaleditor'] = array( - 'type' => 'toggle', - 'section' => 'editing/advancedediting', - 'label-message' => 'tog-externaleditor', - ); - $defaultPreferences['externaldiff'] = array( - 'type' => 'toggle', - 'section' => 'editing/advancedediting', - 'label-message' => 'tog-externaldiff', - ); - } - - $defaultPreferences['forceeditsummary'] = array( + $defaultPreferences['previewonfirst'] = array( 'type' => 'toggle', - 'section' => 'editing/advancedediting', - 'label-message' => 'tog-forceeditsummary', + 'section' => 'editing/preview', + 'label-message' => 'tog-previewonfirst', + ); + $defaultPreferences['previewontop'] = array( + 'type' => 'toggle', + 'section' => 'editing/preview', + 'label-message' => 'tog-previewontop', ); - - $defaultPreferences['uselivepreview'] = array( 'type' => 'toggle', - 'section' => 'editing/advancedediting', + 'section' => 'editing/preview', 'label-message' => 'tog-uselivepreview', ); + } /** @@ -879,7 +943,7 @@ class Preferences { global $wgUseRCPatrol, $wgEnableAPI, $wgRCMaxAge; $watchlistdaysMax = ceil( $wgRCMaxAge / ( 3600 * 24 ) ); - + ## Watchlist ##################################### $defaultPreferences['watchlistdays'] = array( 'type' => 'float', @@ -887,7 +951,7 @@ class Preferences { 'max' => $watchlistdaysMax, 'section' => 'watchlist/displaywatchlist', 'help' => $context->msg( 'prefs-watchlist-days-max' )->numParams( - $watchlistdaysMax )->text(), + $watchlistdaysMax )->text(), 'label-message' => 'prefs-watchlist-days', ); $defaultPreferences['wllimit'] = array( @@ -937,19 +1001,6 @@ class Preferences { ); } - if ( $wgEnableAPI ) { - # Some random gibberish as a proposed default - // @todo Fixme: this should use CryptRand but we may not want to read urandom on every view - $hash = sha1( mt_rand() . microtime( true ) ); - - $defaultPreferences['watchlisttoken'] = array( - 'type' => 'text', - 'section' => 'watchlist/advancedwatchlist', - 'label-message' => 'prefs-watchlist-token', - 'help' => $context->msg( 'prefs-help-watchlist-token', $hash )->escaped() - ); - } - $watchTypes = array( 'edit' => 'watchdefault', 'move' => 'watchmoves', @@ -963,6 +1014,8 @@ class Preferences { foreach ( $watchTypes as $action => $pref ) { if ( $user->isAllowed( $action ) ) { + // Messages: + // tog-watchdefault, tog-watchmoves, tog-watchdeletion, tog-watchcreations $defaultPreferences[$pref] = array( 'type' => 'toggle', 'section' => 'watchlist/advancedwatchlist', @@ -970,6 +1023,19 @@ class Preferences { ); } } + + if ( $wgEnableAPI ) { + $defaultPreferences['watchlisttoken'] = array( + 'type' => 'api', + ); + $defaultPreferences['watchlisttoken-info'] = array( + 'type' => 'info', + 'section' => 'watchlist/tokenwatchlist', + 'label-message' => 'prefs-watchlist-token', + 'default' => $user->getTokenFromOption( 'watchlisttoken' ), + 'help-message' => 'prefs-help-watchlist-token2', + ); + } } /** @@ -988,7 +1054,6 @@ class Preferences { 'min' => 0, ); - if ( $wgVectorUseSimpleSearch ) { $defaultPreferences['vector-simplesearch'] = array( 'type' => 'toggle', @@ -1009,62 +1074,27 @@ class Preferences { 'section' => 'searchoptions/advancedsearchoptions', ); - $nsOptions = array(); - - foreach ( $wgContLang->getNamespaces() as $ns => $name ) { + $nsOptions = $wgContLang->getFormattedNamespaces(); + $nsOptions[0] = $context->msg( 'blanknamespace' )->text(); + foreach ( $nsOptions as $ns => $name ) { if ( $ns < 0 ) { - continue; - } - - $displayNs = str_replace( '_', ' ', $name ); - - if ( !$displayNs ) { - $displayNs = $context->msg( 'blanknamespace' )->text(); + unset( $nsOptions[$ns] ); } - - $displayNs = htmlspecialchars( $displayNs ); - $nsOptions[$displayNs] = $ns; } $defaultPreferences['searchnamespaces'] = array( 'type' => 'multiselect', 'label-message' => 'defaultns', - 'options' => $nsOptions, + 'options' => array_flip( $nsOptions ), 'section' => 'searchoptions/advancedsearchoptions', 'prefix' => 'searchNs', ); } /** - * @param $user User - * @param $context IContextSource - * @param $defaultPreferences Array + * Dummy, kept for backwards-compatibility. */ static function miscPreferences( $user, IContextSource $context, &$defaultPreferences ) { - global $wgContLang; - - ## Misc ##################################### - $defaultPreferences['diffonly'] = array( - 'type' => 'toggle', - 'section' => 'misc/diffs', - 'label-message' => 'tog-diffonly', - ); - $defaultPreferences['norollbackdiff'] = array( - 'type' => 'toggle', - 'section' => 'misc/diffs', - 'label-message' => 'tog-norollbackdiff', - ); - - // Stuff from Language::getExtraUserToggles() - $toggles = $wgContLang->getExtraUserToggles(); - - foreach ( $toggles as $toggle ) { - $defaultPreferences[$toggle] = array( - 'type' => 'toggle', - 'section' => 'personal/i18n', - 'label-message' => "tog-$toggle", - ); - } } /** @@ -1102,7 +1132,7 @@ class Preferences { } # Create preview link - $mplink = htmlspecialchars( $mptitle->getLocalURL( "useskin=$skinkey" ) ); + $mplink = htmlspecialchars( $mptitle->getLocalURL( array( 'useskin' => $skinkey ) ) ); $linkTools[] = "<a target='_blank' href=\"$mplink\">$previewtext</a>"; # Create links to user CSS/JS pages @@ -1236,7 +1266,7 @@ class Preferences { * @param $user User * @param $context IContextSource * @param $formClass string - * @param $remove Array: array of items to remove + * @param array $remove array of items to remove * @return HtmlForm */ static function getFormObject( $user, IContextSource $context, $formClass = 'PreferencesForm', array $remove = array() ) { @@ -1270,15 +1300,17 @@ class Preferences { } /** + * @param $context IContextSource * @return array */ static function getTimezoneOptions( IContextSource $context ) { $opt = array(); - global $wgLocalTZoffset, $wgLocaltimezone; - // Check that $wgLocalTZoffset is the same as $wgLocaltimezone - if ( $wgLocalTZoffset == date( 'Z' ) / 60 ) { - $server_tz_msg = $context->msg( 'timezoneuseserverdefault', $wgLocaltimezone )->text(); + global $wgLocalTZoffset; + $timestamp = MWTimestamp::getLocalInstance(); + // Check that $wgLocalTZoffset is the same as the local time zone offset + if ( $wgLocalTZoffset == $timestamp->format( 'Z' ) / 60 ) { + $server_tz_msg = $context->msg( 'timezoneuseserverdefault', $timestamp->getTimezone()->getName() )->text(); } else { $tzstring = sprintf( '%+03d:%02d', floor( $wgLocalTZoffset / 60 ), abs( $wgLocalTZoffset ) % 60 ); $server_tz_msg = $context->msg( 'timezoneuseserverdefault', $tzstring )->text(); @@ -1339,7 +1371,7 @@ class Preferences { * @param $alldata * @return int */ - static function filterIntval( $value, $alldata ){ + static function filterIntval( $value, $alldata ) { return intval( $value ); } @@ -1360,7 +1392,9 @@ class Preferences { $data[0] = intval( $data[0] ); $data[1] = intval( $data[1] ); $minDiff = abs( $data[0] ) * 60 + $data[1]; - if ( $data[0] < 0 ) $minDiff = - $minDiff; + if ( $data[0] < 0 ) { + $minDiff = - $minDiff; + } } else { $minDiff = intval( $data[0] ) * 60; } @@ -1374,17 +1408,23 @@ class Preferences { } /** + * Handle the form submission if everything validated properly + * * @param $formData * @param $form PreferencesForm * @param $entryPoint string * @return bool|Status|string */ static function tryFormSubmit( $formData, $form, $entryPoint = 'internal' ) { - global $wgHiddenPrefs; + global $wgHiddenPrefs, $wgAuth; $user = $form->getModifiedUser(); $result = true; + if ( !$user->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) { + return Status::newFatal( 'mypreferencesprotected' ); + } + // Filter input foreach ( array_keys( $formData ) as $name ) { if ( isset( self::$saveFilters[$name] ) ) { @@ -1393,41 +1433,39 @@ class Preferences { } } - // Stuff that shouldn't be saved as a preference. - $saveBlacklist = array( - 'realname', - 'emailaddress', - ); - // Fortunately, the realname field is MUCH simpler - if ( !in_array( 'realname', $wgHiddenPrefs ) ) { + // (not really "private", but still shouldn't be edited without permission) + if ( !in_array( 'realname', $wgHiddenPrefs ) && $user->isAllowed( 'editmyprivateinfo' ) ) { $realName = $formData['realname']; $user->setRealName( $realName ); } - foreach ( $saveBlacklist as $b ) { - unset( $formData[$b] ); - } + if ( $user->isAllowed( 'editmyoptions' ) ) { + foreach ( self::$saveBlacklist as $b ) { + unset( $formData[$b] ); + } - # If users have saved a value for a preference which has subsequently been disabled - # via $wgHiddenPrefs, we don't want to destroy that setting in case the preference - # is subsequently re-enabled - # TODO: maintenance script to actually delete these - foreach( $wgHiddenPrefs as $pref ){ - # If the user has not set a non-default value here, the default will be returned - # and subsequently discarded - $formData[$pref] = $user->getOption( $pref, null, true ); - } + # If users have saved a value for a preference which has subsequently been disabled + # via $wgHiddenPrefs, we don't want to destroy that setting in case the preference + # is subsequently re-enabled + # TODO: maintenance script to actually delete these + foreach ( $wgHiddenPrefs as $pref ) { + # If the user has not set a non-default value here, the default will be returned + # and subsequently discarded + $formData[$pref] = $user->getOption( $pref, null, true ); + } - // Keeps old preferences from interfering due to back-compat - // code, etc. - $user->resetOptions(); + // Keep old preferences from interfering due to back-compat code, etc. + $user->resetOptions( 'unused', $form->getContext() ); - foreach ( $formData as $key => $value ) { - $user->setOption( $key, $value ); + foreach ( $formData as $key => $value ) { + $user->setOption( $key, $value ); + } + + $user->saveSettings(); } - $user->saveSettings(); + $wgAuth->updateExternalDB( $user ); return $result; } @@ -1460,11 +1498,12 @@ class Preferences { /** * Try to set a user's email address. * This does *not* try to validate the address. - * Caller is responsible for checking $wgAuth. + * Caller is responsible for checking $wgAuth and 'editmyprivateinfo' + * right. * * @deprecated in 1.20; use User::setEmailWithConfirmation() instead. * @param $user User - * @param $newaddr string New email address + * @param string $newaddr New email address * @return Array (true on success or Status on failure, info string) */ public static function trySetUserEmail( User $user, $newaddr ) { @@ -1479,7 +1518,7 @@ class Preferences { } /** - * @deprecated in 1.19; will be removed in 1.20. + * @deprecated in 1.19 * @param $user User * @return array */ @@ -1549,34 +1588,37 @@ class PreferencesForm extends HTMLForm { * @return String */ function getButtons() { + if ( !$this->getModifiedUser()->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) { + return ''; + } + $html = parent::getButtons(); - $t = SpecialPage::getTitleFor( 'Preferences', 'reset' ); + if ( $this->getModifiedUser()->isAllowed( 'editmyoptions' ) ) { + $t = SpecialPage::getTitleFor( 'Preferences', 'reset' ); - $html .= "\n" . Linker::link( $t, $this->msg( 'restoreprefs' )->escaped() ); + $html .= "\n" . Linker::link( $t, $this->msg( 'restoreprefs' )->escaped() ); - $html = Xml::tags( 'div', array( 'class' => 'mw-prefs-buttons' ), $html ); + $html = Xml::tags( 'div', array( 'class' => 'mw-prefs-buttons' ), $html ); + } return $html; } /** + * Separate multi-option preferences into multiple preferences, since we + * have to store them separately * @param $data array * @return array */ function filterDataForSubmit( $data ) { - // Support for separating MultiSelect preferences into multiple preferences - // Due to lack of array support. foreach ( $this->mFlatFields as $fieldname => $field ) { - $info = $field->mParams; - if ( $field instanceof HTMLMultiSelectField ) { - $options = HTMLFormField::flattenOptions( $info['options'] ); + if ( $field instanceof HTMLNestedFilterable ) { + $info = $field->mParams; $prefix = isset( $info['prefix'] ) ? $info['prefix'] : $fieldname; - - foreach ( $options as $opt ) { - $data["$prefix$opt"] = in_array( $opt, $data[$fieldname] ); + foreach ( $field->filterDataForSubmit( $data[$fieldname] ) as $key => $value ) { + $data["$prefix$key"] = $value; } - unset( $data[$fieldname] ); } } |