Localisation updates for core and extension messages from translatewiki.net (2010...
[lhc/web/wiklou.git] / includes / Preferences.php
index fc2642c..eb5e1f9 100644 (file)
@@ -1,5 +1,30 @@
 <?php
 
+/**
+ * We're now using the HTMLForm object with some customisation to generate the
+ * Preferences form. This object handles generic submission, CSRF protection,
+ * layout and other logic in a reusable manner. We subclass it as a PreferencesForm
+ * to make some minor customisations.
+ *
+ * In order to generate the form, the HTMLForm object needs an array structure
+ * detailing the form fields available, and that's what this class is for. Each
+ * element of the array is a basic property-list, including the type of field,
+ * the label it is to be given in the form, callbacks for validation and
+ * 'filtering', and other pertinent information. Note that the 'default' field
+ * is named for generic forms, and does not represent the preference's default
+ * (which is stored in $wgDefaultUserOptions), but the default for the form
+ * field, which should be whatever the user has set for that preference. There
+ * is no need to override it unless you have some special storage logic (for
+ * instance, those not presently stored as options, but which are best set from
+ * the user preferences view).
+ *
+ * Field types are implemented as subclasses of the generic HTMLFormField
+ * object, and typically implement at least getInputHTML, which generates the
+ * HTML for the input field to be placed in the table.
+ *
+ * Once fields have been retrieved and validated, submission logic is handed
+ * over to the tryUISubmit static method of this class.
+ */
 class Preferences {
        static $defaultPreferences = null;
        static $saveFilters =
@@ -57,7 +82,7 @@ class Preferences {
                        } elseif( $field->validate( $globalDefault, $user->mOptions ) === true ) {
                                $info['default'] = $globalDefault;
                        } else {
-                               throw new MWException( "Global default $globalDefault is invalid for field $name" );
+                               throw new MWException( "Global default '$globalDefault' is invalid for field $name" );
                        }
                }
 
@@ -89,7 +114,7 @@ class Preferences {
        }
 
        static function profilePreferences( $user, &$defaultPreferences ) {
-               global $wgLang;
+               global $wgLang, $wgUser;
                ## User info #####################################
                // Information panel
                $defaultPreferences['username'] =
@@ -110,22 +135,30 @@ class Preferences {
 
                # Get groups to which the user belongs
                $userEffectiveGroups = $user->getEffectiveGroups();
-               $userEffectiveGroupsArray = array();
+               $userGroups = $userMembers = array();
                foreach( $userEffectiveGroups as $ueg ) {
                        if( $ueg == '*' ) {
                                // Skip the default * group, seems useless here
                                continue;
                        }
-                       $userEffectiveGroupsArray[] = User::makeGroupLinkHTML( $ueg );
+                       $groupName  = User::getGroupName( $ueg );
+                       $userGroups[] = User::makeGroupLinkHTML( $ueg, $groupName );
+
+                       $memberName = User::getGroupMember( $ueg );
+                       $userMembers[] = User::makeGroupLinkHTML( $ueg, $memberName );
                }
-               asort( $userEffectiveGroupsArray );
+               asort( $userGroups );
+               asort( $userMembers );
 
                $defaultPreferences['usergroups'] =
                                array(
                                        'type' => 'info',
                                        'label' => wfMsgExt( 'prefs-memberingroups', 'parseinline',
-                                                               count( $userEffectiveGroupsArray ) ),
-                                       'default' => $wgLang->commaList( $userEffectiveGroupsArray ),
+                                               $wgLang->formatNum( count($userGroups) ) ),
+                                       'default' => wfMsgExt( 'prefs-memberingroups-type', array(),
+                                               $wgLang->commaList( $userGroups ),
+                                               $wgLang->commaList( $userMembers )
+                                       ),
                                        'raw' => true,
                                        'section' => 'personal/info',
                                );
@@ -143,7 +176,10 @@ class Preferences {
                                        array(
                                                'type' => 'info',
                                                'label-message' => 'prefs-registration',
-                                               'default' => $wgLang->timeanddate( $user->getRegistration(), true ),
+                                               'default' => wfMsgExt( 'prefs-registration-date-time', 'parsemag',
+                                                       $wgLang->timeanddate( $user->getRegistration(), true ),
+                                                       $wgLang->date( $user->getRegistration(), true ),
+                                                       $wgLang->time( $user->getRegistration(), true ) ),
                                                'section' => 'personal/info',
                                        );
                }
@@ -173,7 +209,6 @@ class Preferences {
                                );
 
                if( $wgAuth->allowPasswordChange() ) {
-                       global $wgUser; // For skin.
                        $link = $wgUser->getSkin()->link( SpecialPage::getTitleFor( 'Resetpass' ),
                                wfMsgHtml( 'prefs-resetpass' ), array(),
                                array( 'returnto' => SpecialPage::getTitleFor( 'Preferences' ) ) );
@@ -205,7 +240,7 @@ class Preferences {
 
                $options = array();
                foreach( $languages as $code => $name ) {
-                       $display = "$code - $name";
+                       $display = wfBCP47( $code ) . ' - ' . $name;
                        $options[$display] = $code;
                }
                $defaultPreferences['language'] =
@@ -217,6 +252,7 @@ class Preferences {
                                );
 
                global $wgContLang, $wgDisableLangConversion;
+               global $wgDisableTitleConversion;
                /* see if there are multiple language variants to choose from*/
                $variantArray = array();
                if( !$wgDisableLangConversion ) {
@@ -233,7 +269,7 @@ class Preferences {
 
                        $options = array();
                        foreach( $variantArray as $code => $name ) {
-                               $display = "$code - $name";
+                               $display = wfBCP47( $code ) . ' - ' . $name;
                                $options[$display] = $code;
                        }
 
@@ -257,7 +293,19 @@ class Preferences {
                                        );
                }
 
-               global $wgMaxSigChars;
+               global $wgMaxSigChars, $wgOut, $wgParser;
+
+               // show a preview of the old signature first
+               $oldsigWikiText = $wgParser->preSaveTransform( "~~~", new Title , $user, new ParserOptions );
+               $oldsigHTML = $wgOut->parseInline( $oldsigWikiText );
+               $defaultPreferences['oldsig'] =
+                       array(
+                                       'type' => 'info',
+                                       'raw' => true,
+                                       'label-message' => 'tog-oldsig',
+                                       'default' => $oldsigHTML,
+                                       'section' => 'personal/signature',
+                       );
                $defaultPreferences['nickname'] =
                                array(
                                        'type' => $wgAuth->allowPropChange( 'nickname' ) ? 'text' : 'info',
@@ -272,9 +320,10 @@ class Preferences {
                                array(
                                        'type' => 'toggle',
                                        'label-message' => 'tog-fancysig',
+                                       'help-message' => 'prefs-help-signature', // show general help about signature at the bottom of the section
                                        'section' => 'personal/signature'
                                );
-
+                               
                ## Email stuff
                
                global $wgEnableEmail;
@@ -284,7 +333,7 @@ class Preferences {
        
                        $defaultPreferences['emailaddress'] =
                                        array(
-                                               'type' => $wgAuth->allowPropChange( 'emailaddress' ) ? 'text' : 'info',
+                                               'type' => $wgAuth->allowPropChange( 'emailaddress' ) ? 'email' : 'info',
                                                'default' => $user->getEmail(),
                                                'section' => 'personal/email',
                                                'label-message' => 'youremail',
@@ -307,13 +356,13 @@ class Preferences {
                                                $time = $wgLang->timeAndDate( $user->getEmailAuthenticationTimestamp(), true );
                                                $d = $wgLang->date( $user->getEmailAuthenticationTimestamp(), true );
                                                $t = $wgLang->time( $user->getEmailAuthenticationTimestamp(), true );
-                                               $emailauthenticated = htmlspecialchars( wfMsg( 'emailauthenticated', $time, $d, $t ) ) . '<br />';
+                                               $emailauthenticated = wfMsgExt( 'emailauthenticated', 'parseinline',
+                                                                                               array($time, $d, $t ) ) . '<br />';
                                                $disableEmailPrefs = false;
                                        } else {
                                                $disableEmailPrefs = true;
-                                               global $wgUser; // wgUser is okay here, it's for display
                                                $skin = $wgUser->getSkin();
-                                               $emailauthenticated = wfMsgHtml( 'emailnotauthenticated' ) . '<br />' .
+                                               $emailauthenticated = wfMsgExt( 'emailnotauthenticated', 'parseinline' ) . '<br />' .
                                                        $skin->link(
                                                                SpecialPage::getTitleFor( 'Confirmemail' ),
                                                                wfMsg( 'emailconfirmlink' ),
@@ -338,7 +387,7 @@ class Preferences {
        
                        }
        
-                       if( $wgEnableUserEmail ) {
+                       if( $wgEnableUserEmail && $user->isAllowed( 'sendemail' ) ) {
                                $defaultPreferences['disablemail'] =
                                                array(
                                                        'type' => 'toggle',
@@ -384,19 +433,24 @@ class Preferences {
                                                        'label-message' => 'tog-enotifminoredits',
                                                        'disabled' => $disableEmailPrefs,
                                                );
+                               global $wgEnotifRevealEditorAddress;
+                               if ( $wgEnotifRevealEditorAddress ) {
+                                       $defaultPreferences['enotifrevealaddr'] =
+                                                       array(
+                                                               'type' => 'toggle',
+                                                               'section' => 'personal/email',
+                                                               'label-message' => 'tog-enotifrevealaddr',
+                                                               'disabled' => $disableEmailPrefs,
+                                                       );
+                               }
                        }
-                       $defaultPreferences['enotifrevealaddr'] =
-                                       array(
-                                               'type' => 'toggle',
-                                               'section' => 'personal/email',
-                                               'label-message' => 'tog-enotifrevealaddr',
-                                               'disabled' => $disableEmailPrefs,
-                                       );
                }
        }
 
        static function skinPreferences( $user, &$defaultPreferences ) {
                ## Skin #####################################
+               global $wgLang, $wgAllowUserCss, $wgAllowUserJs;
+
                $defaultPreferences['skin'] =
                                array(
                                        'type' => 'radio',
@@ -405,6 +459,30 @@ class Preferences {
                                        'section' => 'rendering/skin',
                                );
 
+               # Create links to user CSS/JS pages for all skins
+               # This code is basically copied from generateSkinOptions().  It'd
+               # be nice to somehow merge this back in there to avoid redundancy. 
+               if( $wgAllowUserCss || $wgAllowUserJs ) {
+                       $sk = $user->getSkin();
+                       $linkTools = array();
+                       if( $wgAllowUserCss ) {
+                               $cssPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/common.css' );
+                               $linkTools[] = $sk->link( $cssPage, wfMsgHtml( 'prefs-custom-css' ) );
+                       }
+                       if( $wgAllowUserJs ) {
+                               $jsPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/common.js' );
+                               $linkTools[] = $sk->link( $jsPage, wfMsgHtml( 'prefs-custom-js' ) );
+                       }
+                       $defaultPreferences['commoncssjs'] =
+                               array(
+                                       'type' => 'info',
+                                       'raw' => true,
+                                       'default' => $wgLang->pipeList( $linkTools ),
+                                       'label-message' => 'prefs-common-css-js',
+                                       'section' => 'rendering/skin',
+                               );
+               }
+
                $selectedSkin = $user->getOption( 'skin' );
                if ( in_array( $selectedSkin, array( 'cologneblue', 'standard' ) ) ) {
                        global $wgLang;
@@ -508,23 +586,27 @@ class Preferences {
                                        'label-message' => 'timezonelegend',
                                        'options' => self::getTimezoneOptions(),
                                        'default' => $tzSetting,
+                                       'size' => 20,
                                        'section' => 'datetime/timeoffset',
                                );
        }
 
        static function renderingPreferences( $user, &$defaultPreferences ) {
                ## Page Rendering ##############################
-               $defaultPreferences['underline'] =
-                               array(
-                                       'type' => 'select',
-                                       'options' => array(
-                                               wfMsg( 'underline-never' ) => 0,
-                                               wfMsg( 'underline-always' ) => 1,
-                                               wfMsg( 'underline-default' ) => 2,
-                                       ),
-                                       'label-message' => 'tog-underline',
-                                       'section' => 'rendering/advancedrendering',
-                               );
+               global $wgAllowUserCssPrefs;
+               if( $wgAllowUserCssPrefs ){
+                       $defaultPreferences['underline'] =
+                                       array(
+                                               'type' => 'select',
+                                               'options' => array(
+                                                       wfMsg( 'underline-never' ) => 0,
+                                                       wfMsg( 'underline-always' ) => 1,
+                                                       wfMsg( 'underline-default' ) => 2,
+                                               ),
+                                               'label-message' => 'tog-underline',
+                                               'section' => 'rendering/advancedrendering',
+                                       );
+               }
 
                $stubThresholdValues = array( 0, 50, 100, 500, 1000, 2000, 5000, 10000 );
                $stubThresholdOptions = array();
@@ -537,20 +619,23 @@ class Preferences {
                                        'type' => 'selectorother',
                                        'section' => 'rendering/advancedrendering',
                                        'options' => $stubThresholdOptions,
+                                       'size' => 20,
                                        'label' => wfMsg( 'stub-threshold' ), // Raw HTML message. Yay?
                                );
-               $defaultPreferences['highlightbroken'] =
-                               array(
-                                       'type' => 'toggle',
-                                       'section' => 'rendering/advancedrendering',
-                                       'label' => wfMsg( 'tog-highlightbroken' ), // Raw HTML
-                               );
-               $defaultPreferences['showtoc'] =
-                               array(
-                                       'type' => 'toggle',
-                                       'section' => 'rendering/advancedrendering',
-                                       'label-message' => 'tog-showtoc',
-                               );
+               if( $wgAllowUserCssPrefs ){
+                       $defaultPreferences['highlightbroken'] =
+                                       array(
+                                               'type' => 'toggle',
+                                               'section' => 'rendering/advancedrendering',
+                                               'label' => wfMsg( 'tog-highlightbroken' ), // Raw HTML
+                                       );
+                       $defaultPreferences['showtoc'] =
+                                       array(
+                                               'type' => 'toggle',
+                                               'section' => 'rendering/advancedrendering',
+                                               'label-message' => 'tog-showtoc',
+                                       );
+               }
                $defaultPreferences['nocache'] =
                                array(
                                        'type' => 'toggle',
@@ -569,12 +654,14 @@ class Preferences {
                                        'section' => 'rendering/advancedrendering',
                                        'label-message' => 'tog-showjumplinks',
                                );
-               $defaultPreferences['justify'] =
-                               array(
-                                       'type' => 'toggle',
-                                       'section' => 'rendering/advancedrendering',
-                                       'label-message' => 'tog-justify',
-                               );
+               if( $wgAllowUserCssPrefs ){
+                       $defaultPreferences['justify'] =
+                                       array(
+                                               'type' => 'toggle',
+                                               'section' => 'rendering/advancedrendering',
+                                               'label-message' => 'tog-justify',
+                                       );
+               }
                $defaultPreferences['numberheadings'] =
                                array(
                                        'type' => 'toggle',
@@ -584,7 +671,7 @@ class Preferences {
        }
 
        static function editingPreferences( $user, &$defaultPreferences ) {
-               global $wgUseExternalEditor, $wgLivePreview;
+               global $wgUseExternalEditor, $wgLivePreview, $wgAllowUserCssPrefs;
 
                ## Editing #####################################
                $defaultPreferences['cols'] =
@@ -603,6 +690,20 @@ class Preferences {
                                        'min' => 4,
                                        'max' => 1000,
                                );
+               if( $wgAllowUserCssPrefs ){
+                       $defaultPreferences['editfont'] =
+                                       array(
+                                               'type' => 'select',
+                                               'section' => 'editing/advancedediting',
+                                               'label-message' => 'editfont-style',
+                                               'options' => array(
+                                                       wfMsg( 'editfont-default' ) => 'default',
+                                                       wfMsg( 'editfont-monospace' ) => 'monospace',
+                                                       wfMsg( 'editfont-sansserif' ) => 'sans-serif',
+                                                       wfMsg( 'editfont-serif' ) => 'serif',
+                                               )
+                                       );
+               }
                $defaultPreferences['previewontop'] =
                                array(
                                        'type' => 'toggle',
@@ -615,12 +716,14 @@ class Preferences {
                                        'section' => 'editing/advancedediting',
                                        'label-message' => 'tog-previewonfirst',
                                );
-               $defaultPreferences['editsection'] =
-                               array(
-                                       'type' => 'toggle',
-                                       'section' => 'editing/advancedediting',
-                                       'label-message' => 'tog-editsection',
-                               );
+               if( $wgAllowUserCssPrefs ){
+                       $defaultPreferences['editsection'] =
+                                       array(
+                                               'type' => 'toggle',
+                                               'section' => 'editing/advancedediting',
+                                               'label-message' => 'tog-editsection',
+                                       );
+               }
                $defaultPreferences['editsectiononrightclick'] =
                                array(
                                        'type' => 'toggle',
@@ -684,15 +787,16 @@ class Preferences {
        }
 
        static function rcPreferences( $user, &$defaultPreferences ) {
-               global $wgRCMaxAge, $wgUseRCPatrol;
+               global $wgRCMaxAge, $wgUseRCPatrol, $wgLang;
                ## RecentChanges #####################################
                $defaultPreferences['rcdays'] =
                                array(
-                                       'type' => 'int',
+                                       'type' => 'float',
                                        'label-message' => 'recentchangesdays',
                                        'section' => 'rc/display',
                                        'min' => 1,
                                        'max' => ceil( $wgRCMaxAge / ( 3600*24 ) ),
+                                       'help' => wfMsgExt( 'recentchangesdays-max', array( 'parsemag' ), $wgLang->formatNum( ceil( $wgRCMaxAge / ( 3600*24 ) ) ) ),
                                );
                $defaultPreferences['rclimit'] =
                                array(
@@ -714,7 +818,6 @@ class Preferences {
                                        'section' => 'rc/advancedrc',
                                );
 
-               global $wgUseRCPatrol;
                if( $wgUseRCPatrol ) {
                        $defaultPreferences['hidepatrolled'] =
                                        array(
@@ -742,14 +845,15 @@ class Preferences {
        }
 
        static function watchlistPreferences( $user, &$defaultPreferences ) {
-               global $wgUseRCPatrol;
+               global $wgUseRCPatrol, $wgEnableAPI;
                ## Watchlist #####################################
                $defaultPreferences['watchlistdays'] =
                                array(
-                                       'type' => 'int',
+                                       'type' => 'float',
                                        'min' => 0,
                                        'max' => 7,
                                        'section' => 'watchlist/display',
+                                       'help' => wfMsgHtml( 'prefs-watchlist-days-max' ),
                                        'label-message' => 'prefs-watchlist-days',
                                );
                $defaultPreferences['wllimit'] =
@@ -758,7 +862,8 @@ class Preferences {
                                        'min' => 0,
                                        'max' => 1000,
                                        'label-message' => 'prefs-watchlist-edits',
-                                       'section' => 'watchlist/display'
+                                       'help' => wfMsgHtml( 'prefs-watchlist-edits-max' ),
+                                       'section' => 'watchlist/display',
                                );
                $defaultPreferences['extendwatchlist'] =
                                array(
@@ -796,6 +901,17 @@ class Preferences {
                                        'section' => 'watchlist/advancedwatchlist',
                                        'label-message' => 'tog-watchlisthideliu',
                                );
+               if ( $wgEnableAPI ) {
+                       # Some random gibberish as a proposed default
+                       $hash = sha1( mt_rand() . microtime( true ) );
+                       $defaultPreferences['watchlisttoken'] =
+                                       array(
+                                               'type' => 'text',
+                                               'section' => 'watchlist/advancedwatchlist',
+                                               'label-message' => 'prefs-watchlist-token',
+                                               'help' => wfMsgHtml( 'prefs-help-watchlist-token', $hash )
+                                       );
+               }
 
                if ( $wgUseRCPatrol ) {
                        $defaultPreferences['watchlisthidepatrolled'] =
@@ -924,8 +1040,12 @@ class Preferences {
                }
        }
 
+       /**
+        * @param object $user The user object
+        * @return array Text/links to display as key; $skinkey as value
+        */
        static function generateSkinOptions( $user ) {
-               global $wgDefaultSkin;
+               global $wgDefaultSkin, $wgLang, $wgAllowUserCss, $wgAllowUserJs;
                $ret = array();
 
                $mptitle = Title::newMainPage();
@@ -946,23 +1066,28 @@ class Preferences {
                $sk = $user->getSkin();
 
                foreach( $validSkinNames as $skinkey => $sn ) {
+                       $linkTools = array();
+
+                       # Mark the default skin
+                       if( $skinkey == $wgDefaultSkin ) {
+                               $linkTools[] = wfMsgHtml( 'default' );
+                       }
+
+                       # Create preview link
                        $mplink = htmlspecialchars( $mptitle->getLocalURL( "useskin=$skinkey" ) );
-                       $previewlink = "(<a target='_blank' href=\"$mplink\">$previewtext</a>)";
-                       $extraLinks = '';
-                       global $wgAllowUserCss, $wgAllowUserJs;
+                       $linkTools[] = "<a target='_blank' href=\"$mplink\">$previewtext</a>";
+
+                       # Create links to user CSS/JS pages
                        if( $wgAllowUserCss ) {
                                $cssPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/' . $skinkey . '.css' );
-                               $customCSS = $sk->link( $cssPage, wfMsgHtml( 'prefs-custom-css' ) );
-                               $extraLinks .= " ($customCSS)";
+                               $linkTools[] = $sk->link( $cssPage, wfMsgHtml( 'prefs-custom-css' ) );
                        }
                        if( $wgAllowUserJs ) {
                                $jsPage = Title::makeTitleSafe( NS_USER, $user->getName() . '/' . $skinkey . '.js' );
-                               $customJS = $sk->link( $jsPage, wfMsgHtml( 'prefs-custom-js' ) );
-                               $extraLinks .= " ($customJS)";
+                               $linkTools[] = $sk->link( $jsPage, wfMsgHtml( 'prefs-custom-js' ) );
                        }
-                       if( $skinkey == $wgDefaultSkin )
-                               $sn .= ' (' . wfMsgHtml( 'default' ) . ')';
-                       $display = "$sn $previewlink{$extraLinks}";
+
+                       $display = $sn . ' ' . wfMsg( 'parentheses', $wgLang->pipeList( $linkTools ) );
                        $ret[$display] = $skinkey;
                }
 
@@ -982,7 +1107,7 @@ class Preferences {
                        }
 
                        $idCnt = 0;
-                       $epoch = '20010115161234'; # Wikipedia day
+                       $epoch = wfTimestampNow();
                        foreach( $dateopts as $key ) {
                                if( $key == 'default' ) {
                                        $formatted = wfMsgHtml( 'datedefault' );
@@ -1175,18 +1300,18 @@ class Preferences {
                );
 
                if( $wgEnableEmail ) {
-                       $newadr = $formData['emailaddress'];
-                       $oldadr = $wgUser->getEmail();
-                       if( ( $newadr != '' ) && ( $newadr != $oldadr ) ) {
+                       $newaddr = $formData['emailaddress'];
+                       $oldaddr = $wgUser->getEmail();
+                       if( ( $newaddr != '' ) && ( $newaddr != $oldaddr ) ) {
                                # the user has supplied a new email address on the login page
                                # new behaviour: set this new emailaddr from login-page into user database record
-                               $wgUser->setEmail( $newadr );
+                               $wgUser->setEmail( $newaddr );
                                # but flag as "dirty" = unauthenticated
                                $wgUser->invalidateEmail();
                                if( $wgEmailAuthentication ) {
                                        # Mail a temporary password to the dirty address.
                                        # User can come back through the confirmation URL to re-enable email.
-                                       $result = $wgUser->sendConfirmationMail();
+                                       $result = $wgUser->sendConfirmationMail( $oldaddr != '' );
                                        if( WikiError::isError( $result ) ) {
                                                return wfMsg( 'mailerror', htmlspecialchars( $result->getMessage() ) );
                                        } elseif( $entryPoint == 'ui' ) {
@@ -1194,10 +1319,10 @@ class Preferences {
                                        }
                                }
                        } else {
-                               $wgUser->setEmail( $newadr );
+                               $wgUser->setEmail( $newaddr );
                        }
-                       if( $oldadr != $newadr ) {
-                               wfRunHooks( 'PrefsEmailAudit', array( $wgUser, $oldadr, $newadr ) );
+                       if( $oldaddr != $newaddr ) {
+                               wfRunHooks( 'PrefsEmailAudit', array( $wgUser, $oldaddr, $newaddr ) );
                        }
                }